hdu 2476 区间dp
题意:给一个串s,一个串t。将s粉刷成t ,每次可以粉刷一个区间,将一个区间的字母粉刷成一个相同,最少粉刷需要多少次。
思路:区间dp
假设我们没有串s,而 将 另一个与 t 完全不相同的串粉刷成t。
这样我们对t进行一个处理,dp[i][j]表示从i到j需要粉刷多少次。这个区间dp并不难。
由于可能有s[i]=t[i]导致的不必要的粉刷,处理完t之后,就可以对s,t之间相同的字符处理了。
假设 f[j] 是s->t的最优数目,如果s[j+1]==t[j+1], 那么f[j+1]就不必+1粉刷了,f[j+1]=f[j];
但是如果s[j+1]!=t[j+1],如何进行更新?
考虑再把他分段,分成[1,k][k+1,j]两个区间
[1,k]的最佳情况是f[k],[k+1,j]就是dp[k+1][j];
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define fi first #define se second #define all(v) v.begin(),v.end() #define mem(a) memset(a,0,sizeof(a)) const int N =103; const ll mod =1e9+7; const int INF = 1e9+4; const double eps = 1e-7; char s[N],t[N]; int dp[N][N]; int f[N]; int main(){ while(scanf("%s %s",s+1,t+1)!=EOF){ int n = strlen(s+1); for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j) dp[i][j]=INF; for(int i=1;i<=n;++i) dp[i][i]=1; for(int i=1;i<=n;++i) f[i]=INF; for(int len=1;len<n;++len){ for(int i=1;i+len<=n;++i){ int j =i+len; dp[i][j] = dp[i+1][j]+(t[i]!=t[i+1]); for(int k=i+1;k<=j;++k){ if(t[i]==t[k]) dp[i][j]= min(dp[i][j],dp[i+1][k]+dp[k+1][j]); } } } for(int i=1;i<=n;++i){ if(s[i]==t[i])f[i]=f[i-1]; else { f[i]=f[i-1]+1; for(int j=0;j<=i;++j) f[i]=min(f[i],f[j]+dp[j+1][i]); } } printf("%d\n",f[n]); } return 0; }