2 条题解
-
0
区间DP
设为从到这段区间被修正为回文串的最小花费,为添加字符的花费,为删去字符的花费,为题目给出的串。为可以用如下几个转移:
- 用区间转移:这种转移相当于在区间的左边加入一个字符,让变为回文的方法为在左边删去该字符或在右边加上该字符,有转移方程:
- 用区间转移:这种转移相当于在区间的右边加入一个字符,方法同上:
- 当前区间满足,直接用转移:
然后就可以愉快地写代码了:
#include<bits/stdc++.h> using namespace std; const int N=2010; int n,m; char s[N]; int c[255][2]; int f[N][N]; int main(){ cin>>m>>n; scanf("%s",s+1); for(int i=1;i<=m;++i){ char op[2]; int a,b; scanf("%s %d %d",op,&a,&b); c[op[0]][0]=a; c[op[0]][1]=b; } memset(f,0x3f,sizeof f); for(int i=1;i<=n;++i)f[i][i]=0; for(int i=0;i<=n+1;++i){ for(int j=0;j<i;++j)f[i][j]=0; } for(int k=1;k<=n;++k){ for(int i=1;k+i<=n;++i){ int j=k+i; f[i][j]=min(f[i+1][j]+min(c[s[i]][0],c[s[i]][1]), f[i][j-1]+min(c[s[j]][0],c[s[j]][1])); if(s[i]==s[j]){ if(j-i==1)f[i][j]=0; else f[i][j]=min(f[i][j],f[i+1][j-1]); } } } cout<<f[1][n]<<endl; } -
0
by hansang:
#include <bits/stdc++.h> using namespace std; const int N = 2e3 + 10; typedef long long LL; char s[N]; LL f[N][N]; struct node{LL x, y, mn;} a[N]; int main(){ int n, m; scanf("%d%d", &m, &n); scanf("%s", s + 1); for(int i = 1; i <= m; i++){ char ss[5]; scanf("%s", ss); int t = ss[0] - 'a'; scanf("%lld%lld", &a[t].x, &a[t].y); a[t].mn = min(a[t].x, a[t].y); } memset(f, 0x3f, sizeof(f)); for(int i = n; i >= 1; i--){ f[i][i] = 0; for(int j = i + 1; j <= n; j++){ int t1 = s[i] - 'a', t2 = s[j] - 'a'; f[i][j] = min(f[i+1][j] + a[t1].mn, f[i][j-1] + a[t2].mn); if(s[i] == s[j]){ if(i + 1 == j) f[i][j] = 0; else f[i][j] = min(f[i][j], f[i+1][j-1]); } } } printf("%lld\n", f[1][n]); return 0; }
- 1
信息
- ID
- 2301
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 7
- 标签
- 递交数
- 16
- 已通过
- 10
- 上传者