您的位置:首页 > 其它

HDU 2476 区间DP--转移思考方向

2017-08-03 22:27 501 查看

区间DP–转移思考方向

题意:

有两个字符串,现在有一个操作可以把第一个字字符串的某区间改成同一个字母,问最少多少步可以变成第二个字符串。

思路:

思考问题的方向,关键点在于有的区间端点相同的话可以直接一步操作,问题是很难直接用区间DP去比较两个字符串,四维的不行。换一种思考方式,如果能先把最坏的情况算出来,也就是直接构造一个字符串2的最少步数算出,就可以再找出特殊情况,所以对s2DP,从后往前,长度依次增大,每次寻找最少的步数,当然需要初始化。很多博客上对dp[i][j]=dp[i+1][j]+1; 不太清晰,其实在DP的时候是从后往前的,每次相当于增添了第i个字母,最坏当然是只改变一个第i区间了,而dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]); 的意义在于如果第i个字母与后边的某一个字母相同的话可以利用已经算出的结果,把后边的去区间分为两部分,因为第i和第k在区间转换字母的时候只需一次就行

所以记录最小的就行。

区间DP很重要的一点就是每次计算都在已经找的区间种选择最小的期望值,利用的是已经算出的结果。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 1005;

int dp[maxn][maxn];
char s1[maxn],s2[maxn];
int ans[maxn];

int main(int argc, char const *argv[])
{
//freopen("in.txt","r",stdin);

while(scanf("%s%s",s1,s2) != EOF) {
int len = strlen(s2);
for(int i = 0;i < len; i++) {
for(int j = i;j < len; j++) {
dp[i][j] = j - i + 1;
}
}
for(int i = len-2;i >= 0; i--) {
for(int j = i;j < len; j++) {
dp[i][j] = dp[i+1][j] + 1;
for(int k = i + 1;k <= j; k++) {
if(s2[i] == s2[k]) {
dp[i][j] = min(dp[i][j] , dp[i+1][k] + dp[k+1][j]);
}
}
}
}
for(int i = 0;i < len; i++) ans[i] = dp[0][i];
for(int i = 0;i < len; i++) {
if(s1[i] == s2[i]) {
if(i == 0) ans[0] = 0;
else ans[i] = ans[i-1];
}
for(int j = 0;j < i; j++) {
ans[i] = min(ans[i],ans[j] + dp[j+1][i]);
}
}
printf("%d\n",ans[len-1]);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp