您的位置:首页 > 其它

【DP+记忆化搜索】PKU-1390-Blocks

2012-02-27 00:43 260 查看
http://poj.org/problem?id=1390



又是黑书上的一道坑爹题,不过话说越坑爹越能学到东西……这里就贴上黑书上的解析吧……

分析 线性DP
参照《算法艺术》上的算法
题目的方块可以表示称color[i],len[i],1<=i<=l

这里l表示有多少"段"不同的颜色方块

color[i]表示第i段的颜色,len[i]表示第i段的方块长度

让f[i,j,k]表示把(color[i],len[i]),(color[i+1],len[i+1]),...,(color[j-1],len[j-1]),(color[j],len[j]+k)合并的最大得分

考虑(color[j],len[j]+k)这一段,要不马上消掉,要不和前面的若干段一起消掉

1.如果马上消掉,就是f[i,j-1,0]+(len[j]+k)^2

2.如果和前面的若干段一起消,可以假设这"若干段"中最后一段是p,则此时的得分是f[i,p,k+len[j]]+f[p+1,j-1,0]

于是f[i,j,k] = max{ f[i,j-1,0]+(len[j]+k)^2, f[i,p,k+len[j]]+f[p+1,j-1,0] }

复杂度
O(n^4),时间效率很低,但可以利用更新解的必要条件color[p] = color[j]来优化算法
#include<iostream>
using namespace std;
int cl[201],len[201],dp[201][201][201];
int dfs(int s,int e,int l)
{
int i,sum,tmp;
if(dp[s][e][l]!=-1)return dp[s][e][l];
if(s>e)return 0;
sum=dfs(s,e-1,0)+(len[e]+l)*(len[e]+l);
for(i=e-1;i>=s;i--)
if(cl[i]==cl[e])
{
tmp=dfs(s,i,len[e]+l)+dfs(i+1,e-1,0);
if(tmp>sum)sum=tmp;
}
return dp[s][e][l]=sum;
}
int main()
{
//freopen("a.txt","r",stdin);
int t,i,m,n,c=1,x;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
len[m=1]=1;
scanf("%d",&cl[1]);
for(i=1;i<n;i++)
{
scanf("%d",&x);
if(x!=cl[m])
{
cl[++m]=x;
len[m]=0;
}
len[m]++;
}
memset(dp,-1,sizeof(dp));
printf("Case %d: %d\n",c++,dfs(1,m,0));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: