小M的迴文串Description
小M喜歡迴文串,迴文串就是從左往右和從右往左讀都一樣的字串。
現在小X找到小M給了他一個字串S,希望小M將它變成迴文串。
小M可以進行如下三類操作:
- add 在字串的任意位置添加一個字元
- erase 刪除一個字元
- change one letter to another 將某個字元變成另一個
然而,每種操作只能對規定的字元有效。如,小M只能允許erase 'a', add 'b', change 'c' to 'd',且沒有其他動作可以使用。 世界上沒有免費的午餐,小M的每次操作都有一定的花費。
Input Format
第一行一個字串,表示小M需要修改的字串 (length≤50)
第二行一個數N, 表示小M可以使用的操作 (N≤50 )
接下來N行,每行一個可以使用的操作,有下面三種形式:
"add c x" : 表示將一個字元c加入到串中需要的花費為x
"erase c x" : 表示將一個字元c從串中刪除需要的花費為x
"change c1 c2 x" : 表示將某個字元c1變為c2需要的花費為x
注意,"change c1 c2 x" 不允許將c2變成c1
滿足 x≤100000,c1<>c2 ,
且任兩行操作不同
Output Format
一行一個數,表示小M將初始的字串轉為迴文串的最小花費,如果不可能,輸出-1
Sample Input
caaaaaab6change b a 100000change c a 100000change c d 50000change b e 50000erase d 50000erase e 49999
Sample Output
199999
題解:有幾組資料過不了。不知為什麼···。先貼上代碼,以後再想。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;char s[100];int ch[40][40], er[40], add[40];int dp[100][100];const int INF = 999999999;void init(){ for(int i = 0; i < 26; i++) { er[i] = add[i] = INF; for(int j = 0; j < 26; j++) ch[i][j] = (i == j ? 0 : INF); }}void Floyd(){ int i, j, k; for(k = 0; k < 26; k++) for(i = 0; i < 26; i++) for(j = 0; j < 26; j++) ch[i][j] = min(ch[i][j], ch[i][k] + ch[k][j]); for(i = 0; i < 26; i++) for(j = 0; j < 26; j++) if(ch[i][j] != INF) { er[i] = min(er[i], ch[i][j] + er[j]); add[i] = min(add[i], ch[i][j] + add[j]); }}int operDp(){ int i, j; int len = strlen(s); memset(dp,0,sizeof(dp)); for(i = 0; i < len; i++) for(j = i + 1; j < len; j++) dp[i][j] = INF; for(i = len - 2; i >= 0; i--) { for(j = i + 1; j < len; j++) { if(s[i] != s[j]) { if(er[s[i]-'a'] != INF) //在左端刪掉s[i] dp[i][j] = min(dp[i+1][j] + er[s[i]-'a'], dp[i][j]); if(add[s[i]-'a'] != INF) //在右端加上s[i] dp[i][j] = min(dp[i+1][j] + add[s[i]-'a'], dp[i][j]); if(er[s[j]-'a'] != INF) //在右端刪掉s[j] dp[i][j] = min(dp[i][j-1] + er[s[j]-'a'], dp[i][j]); if(add[s[j]-'a'] != INF) //在左端加上s[j] dp[i][j] = min(dp[i][j-1] + add[s[j]-'a'], dp[i][j]); if(ch[s[i]-'a'][s[j]-'a'] != INF) dp[i][j] = min(dp[i+1][j-1] + ch[s[i]-'a'][s[j]-'a'], dp[i][j]); //將左端改成與右端一樣 if(ch[s[j]-'a'][s[i]-'a'] != INF) dp[i][j] = min(dp[i+1][j-1] + ch[s[j]-'a'][s[i]-'a'], dp[i][j]); //將右端改成與左端一樣 } else { if(er[s[i]-'a'] != INF) //在左端刪掉s[i] dp[i][j] = min(dp[i+1][j] + er[s[i]-'a'], dp[i][j]); if(er[s[i]-'a'] != INF) //在右端加上s[i] dp[i][j] = min(dp[i+1][j] + add[s[i]-'a'], dp[i][j]); if(er[s[j]-'a'] != INF) //在右端刪掉s[j] dp[i][j] = min(dp[i][j-1] + er[s[j]-'a'], dp[i][j]); if(er[s[j]-'a'] != INF) //在左端加上s[j] dp[i][j] = min(dp[i][j-1] + add[s[j]-'a'], dp[i][j]); dp[i][j] = min(dp[i+1][j-1], dp[i][j]); } } } if(dp[0][len-1] == INF) return -1; return dp[0][len-1];}int main(){ int n, v; char c1[3], c2[3], oper[100]; while(scanf("%s",s) != EOF) { init(); scanf("%d",&n); while(n--) { scanf("%s",oper); if(strcmp(oper,"change") == 0) { scanf("%s%s%d",c1, c2, &v); ch[c1[0]-'a'][c2[0]-'a'] = v; } else if(strcmp(oper,"erase") == 0) { scanf("%s%d",c1,&v); er[c1[0]-'a'] = v; } else { scanf("%s%d",c1,&v); add[c1[0]-'a'] = v; } } Floyd(); printf("%d\n",operDp()); } return 0;}