题目大意:
现在有一串字符(不一定是回文串),每个字母都有添加和删去的花费,问将这一串字符变成回文串的最小花费是 多少
分析:
方法一:区间dp 实际上删去和添加一个字母是等价的,因为添加和删去都是为了让这一段变成回文的,这对于我们dp[i][j]([i,j] 这一段变成回文所需要花的花费)来讲,我们只要取删除和添加中的最小花费就行了。而状态转移方程也是比较好 推的: s[i]==s[j]则说明dp[i][j]=dp[i+1][j-1],否则 dp[i][j]=min(dp[i+1][j]+cnt[s[i]-'a'],dp[i][j-1]+cnt[s[j]-'a']) 最后的dp[0][m-1]就是我们需要的答案 方法二:dfs,看代码
code1(区间dp):
#define debug #include<stdio.h> #include<math.h> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<functional> #include<iomanip> #include<map> #include<set> #define pb push_back #define dbg(x) cout<<#x<<" = "<<(x)<<endl; #define lson l,m,rt<<1 #define cmm(x) cout<<"("<<(x)<<")"; #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; const int maxn=1e5; const int INF=0x3f3f3f3f; const ll inf=0x7fffff; const int mod=1e9+7; const int MOD=10007; //---- //define int dp[2005][2005]; int cnt[26]; char s[maxn]; //solve void solve() { int n,m,dec,adc; char tmp; scanf("%d%d",&n,&m); getchar(); scanf("%s",s); getchar(); for(int i=0; i<n; i++) { scanf("%c%d%d",&tmp,&dec,&adc); getchar(); cnt[tmp-'a']=min(dec,adc); } for(int i=1; i<m; i++) { dp[i][i]=0;//单个字符就是一个回文,所以赋值为0 for(int j=0; j+i<m; j++) { if(s[j]==s[j+i])dp[j][j+i]=dp[j+1][j+i-1]; else dp[j][j+i]=min(dp[j+1][j+i]+cnt[s[j]-'a'],dp[j][j+i-1]+cnt[s[j+i]-'a']); } } printf("%d",dp[0][m-1]); } int main() { // ios_base::sync_with_stdio(0); #ifdef debug freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif // cin.tie(0); // cout.tie(0); solve(); return 0; }
code2(dfs):
#define debug #include<stdio.h> #include<math.h> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<functional> #include<iomanip> #include<map> #include<set> #define pb push_back #define dbg(x) cout<<#x<<" = "<<(x)<<endl; #define lson l,m,rt<<1 #define cmm(x) cout<<"("<<(x)<<")"; #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; const int maxn=1e5; const ll INF=0x3f3f3f3f; const ll inf=0x7fffff; const int mod=1e9+7; const int MOD=10007; //---- //define int dp[2005][2005]; int cnt[26]; char s[maxn]; //dfs int dfs(int l,int r){ if(l>=r)return dp[l][r]=0; if(dp[l][r]!=-1)return dp[l][r]; if(s[l]!=s[r]){ return dp[l][r]=min(dfs(l+1,r)+cnt[s[l]-'a'],dfs(l,r-1)+cnt[s[r]-'a']); } return dp[l][r]=dfs(l+1,r-1); } //solve void solve() { int n,m,dec,adc; char tmp; scanf("%d%d",&n,&m); getchar(); scanf("%s",s); getchar(); memset(dp,-1,sizeof(dp)); for(int i=0;i<n;i++){ scanf("%c%d%d",&tmp,&dec,&adc); getchar(); cnt[tmp-'a']=min(dec,adc); } printf("%d",dfs(0,m-1)); } int main() { // ios_base::sync_with_stdio(0); #ifdef debug freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif // cin.tie(0); // cout.tie(0); solve(); return 0; }