您的位置:首页 > 大数据 > 人工智能

la 4394 string painter 区间dp

2016-03-14 15:26 344 查看
开始练dp了,要好好练啊。

这是一道区间dp的题目,每次对序列的一个区间操作,区间dp有一个特点是,对于某一个区间,如果你没有对这个区间进行操作,而对这个区间的子区间进行操作,那么这个区间就没有必要再操作了,否则对子区间的操作就成了费操作,这个是区间dp的决策,决策是对本区间进行大操作,还是分到其他子区间(o(n))的分法

本题就是这样,dp【i】【j】表示从i到j的原序列变成末序列需要的费用,显然看是否对序列本身操作,然后分到子区间中,这个时候发现对本身进行操作之后,就会变成一个全是同种字母的区间,把他们也加入状态,还是同上的dp,就可以得到答案,不过百度大神有先算白板的,复杂度更低一点

每个字符串,到末状态,如果说修改本身的话,一定是在末状态的头和尾相等的时候修改,否则和分到子区间再分别修改是一样的,这样就又减少了决策时转移的状态数

反正我是A了……好题啊,充分利用了区间dp的性质

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
const int maxn = 100;
const int INF = 111111111;
char sa[maxn],sb[maxn];
int d[maxn][maxn][27];
int length;
//一坨到对应的
int dp(int l,int r,int col)//26表示原串
{
int tem;
if (d[l][r][col] != -1) return d[l][r][col];
if (l > r) return 0;//只有0个,相等
if (l == r) {//只有一个
if (col == 26) d[l][r][col] = (1 - (sa[l] == sb[l]));
else d[l][r][col] = (1 - (col == sb[l] - 'a'));
return d[l][r][col];
}
//涂整个
if (sb[l] == sb[r]) tem = dp(l + 1,r - 1,sb[l] - 'a') + 1;
//else tem = min(dp(l + 1,r,sb[l] - 'a'),dp(l , r - 1,sb[r] - 'a')) + 1; 加了这句话会慢几乎一倍,没有深刻分析问题
//分开
for(int i = l + 1; i <= r; i++)
tem = min(tem,dp(l,i - 1,col) + dp(i,r,col));
d[l][r][col] = tem;

return tem;
}
int main()
{
while(scanf("%s %s",sa,sb) != EOF){
length = strlen(sa);
memset(d,-1,sizeof(d));
printf("%d\n",dp(0,length - 1,26));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm dp 区间