标签:r++ code log clu using 修改 回文 while ==
记忆化搜索,$dp$。
$dp[L][R]$表示将区间$[L,R]$修改为一个回文串需要的最小代价。转移很容易写,区间$dp$或者记忆化搜索都可以。
区间$dp$:
#include <cstdio> #include <cmath> #include <set> #include <cstring> #include <algorithm> using namespace std; char s[2010],op[5]; int dp[2010][2010]; int c[30][2]; int m,n; int main() { while(~scanf("%d%d",&m,&n)) { scanf("%s",s); for(int i=0;i<m;i++) { scanf("%s",op); scanf("%d%d",&c[op[0]-‘a‘][0],&c[op[0]-‘a‘][1]); } int len=strlen(s); for(int L=0;L<len;L++) { for(int R=L;R<len;R++) { dp[L][R]=0x7FFFFFFF; } } for(int x = 1;x<=len;x++) { for(int L=0;L<len;L++) { if(x==1) { dp[L][L]=0; continue; } int R = L+x-1; if(R>=len) continue; if(x==2&&s[L]==s[R]) { dp[L][R]=0; continue; } if(s[L]==s[R]) dp[L][R] = min(dp[L][R],dp[L+1][R-1]); dp[L][R] = min(dp[L][R], dp[L+1][R]+c[s[L]-‘a‘][0]); dp[L][R] = min(dp[L][R], dp[L+1][R]+c[s[L]-‘a‘][1]); dp[L][R] = min(dp[L][R], dp[L][R-1]+c[s[R]-‘a‘][0]); dp[L][R] = min(dp[L][R], dp[L][R-1]+c[s[R]-‘a‘][1]); } } printf("%d\n",dp[0][n-1]); } return 0; }
记忆化搜索:
#include <cstdio> #include <cmath> #include <set> #include <cstring> #include <algorithm> using namespace std; char s[2010],op[5]; int dp[2010][2010]; int c[30][2]; int m,n,len; int dfs(int L,int R) { if(dp[L][R]!=0x7FFFFFFF) return dp[L][R]; if(R-L==0) dp[L][R]=0; else if(R-L==1&&s[L]==s[R]) dp[L][R]=0; else { int mn = 0x7FFFFFFF; if(s[L]==s[R]) mn = min(mn,dfs(L+1,R-1)); mn = min(mn , dfs(L+1,R)+c[s[L]-‘a‘][0]); mn = min(mn , dfs(L+1,R)+c[s[L]-‘a‘][1]); mn = min(mn , dfs(L,R-1)+c[s[R]-‘a‘][0]); mn = min(mn , dfs(L,R-1)+c[s[R]-‘a‘][1]); dp[L][R] = mn; } return dp[L][R]; } int main() { while(~scanf("%d%d",&m,&n)) { scanf("%s",s); for(int i=0;i<m;i++) { scanf("%s",op); scanf("%d%d",&c[op[0]-‘a‘][0],&c[op[0]-‘a‘][1]); } len=strlen(s); for(int L=0;L<len;L++) { for(int R=L;R<len;R++) { dp[L][R]=0x7FFFFFFF; } } printf("%d\n",dfs(0,n-1)); } return 0; }
标签:r++ code log clu using 修改 回文 while ==
原文地址:http://www.cnblogs.com/zufezzt/p/6816757.html