您的位置:首页 > 其它

HDU 2476 区间DP

2016-03-04 20:45 453 查看
HDU 2476

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2476

题意:

把字符串a变成字符串b,每次可以使一段区间变成同一个字母。问最少变换次数。

思路:

明显的区间DP。然而没有弄清楚转移方程是什么。

题解仔细一想还是挺神奇的。先假设所有的a字符串中字母和b中均不相同,dp[i][j]表示最小化把i-j刷成b字符串的代价。遍历i-j中字母,若存在b[i] == b[k],则可以有转移方程dp[i+1][k]+dp[k+1][j]。

然后回到现实情况。Ans[i]表示从头刷到第j个字母代价。详情转移见代码。

没想出本题原因

1.基于a[i] == b[i] && a[k] == b[k]的讨论,造成讨论变成高维度难以进行。

源码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 100 + 6;
int dp[MAXN][MAXN];
int ans[MAXN];
char a[MAXN], b[MAXN];
int main()
{
while(scanf("%s%s", a, b) != EOF){
int n = strlen(a);
memset(dp, 0, sizeof dp);
for(int j = 0 ; j < n ; j++){
for(int i = j; i >= 0 ; i--){
dp[i][j] = dp[i + 1][j] + 1;
for(int k = i + 1; k <= j ; k++)
if(b[i] == b[k]) dp[i][j] = min(dp[i][j], dp[i + 1][k] + dp[k + 1][j]);
}
}
//        for(int i = 0 ; i < n ; i++) printf("%d ", dp[0][i]);
//        printf("\n");
memset(ans, 0, sizeof ans);
for(int i = 0 ; i < n ; i++) ans[i] = dp[0][i];
for(int i = 0 ; i < n ; i++){
if(a[i] == b[i]){
if(i == 0) ans[i] = 0;
else ans[i] = ans[i - 1];
}
else{
for(int k = 0 ; k < i ; k++) ans[i] = min(ans[i], ans[k] + dp[k + 1][i]);
}
}
printf("%d\n", ans[n - 1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: