POJ 1390 Blocks
2016-07-19 11:07
435 查看
定义f[i][j][ex_len]的状态为,清除i,j之间的木块的最大值,且与j有相邻的且长度为ex_len的木块,那么设j与ex_len连起来的木块为Q。
则有两种选择,一种选择是点掉Q,然后继续点掉i~j-1范围内的木块取最大值,他的值result=dp(i,j-1,0)+(len[j]+ex_len)*(len[j]+ex_len);
另一种选择是从i~j-1中寻找一个与j,ex_len颜色相同的木块k,消除k+1~j-1的木块,这样值为r=dp(i,k,len[j]+ex_len)+dp(k+1.j-1,0)(当然k是在i~j-1中的与j木块相同的木块,需要一个for循环来枚举);
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn=200+5;
int p[maxn],color[maxn],len[maxn];
int f[maxn][maxn][maxn];
using namespace std;
int dp(int i,int j,int ex_len)
{
if(f[i][j][ex_len]!=-1) return f[i][j][ex_len];
int result=(len[j]+ex_len)*(len[j]+ex_len);
if(i==j) return result;
result=result+dp(i,j-1,0);
for(int k=i;k<=j-1;k++)
{
if(color[k]!=color[j]) continue;
int r=dp(i,k,len[j]+ex_len)+dp(k+1,j-1,0);
result=max(result,r);
}
f[i][j][ex_len]=result;
return result;
}
int main()
{
int n,t,cnt=1,kase=0;
scanf("%d",&t);
while(t--)
{
cnt=1;
scanf("%d",&n);
memset(f,-1,sizeof(f));
memset(len,0,sizeof(len));
memset(len,0,sizeof(len));
for(int i=1;i<=n;i++)
{
scanf("%d",&p[i]);
if(i>1&&p[i]!=p[i-1]) cnt++;
color[cnt]=p[i];
len[cnt]++;
}
printf("Case %d: %d\n",++kase,dp(1,cnt,0));
}
return 0;
}
则有两种选择,一种选择是点掉Q,然后继续点掉i~j-1范围内的木块取最大值,他的值result=dp(i,j-1,0)+(len[j]+ex_len)*(len[j]+ex_len);
另一种选择是从i~j-1中寻找一个与j,ex_len颜色相同的木块k,消除k+1~j-1的木块,这样值为r=dp(i,k,len[j]+ex_len)+dp(k+1.j-1,0)(当然k是在i~j-1中的与j木块相同的木块,需要一个for循环来枚举);
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn=200+5;
int p[maxn],color[maxn],len[maxn];
int f[maxn][maxn][maxn];
using namespace std;
int dp(int i,int j,int ex_len)
{
if(f[i][j][ex_len]!=-1) return f[i][j][ex_len];
int result=(len[j]+ex_len)*(len[j]+ex_len);
if(i==j) return result;
result=result+dp(i,j-1,0);
for(int k=i;k<=j-1;k++)
{
if(color[k]!=color[j]) continue;
int r=dp(i,k,len[j]+ex_len)+dp(k+1,j-1,0);
result=max(result,r);
}
f[i][j][ex_len]=result;
return result;
}
int main()
{
int n,t,cnt=1,kase=0;
scanf("%d",&t);
while(t--)
{
cnt=1;
scanf("%d",&n);
memset(f,-1,sizeof(f));
memset(len,0,sizeof(len));
memset(len,0,sizeof(len));
for(int i=1;i<=n;i++)
{
scanf("%d",&p[i]);
if(i>1&&p[i]!=p[i-1]) cnt++;
color[cnt]=p[i];
len[cnt]++;
}
printf("Case %d: %d\n",++kase,dp(1,cnt,0));
}
return 0;
}
相关文章推荐
- 递归与非递归的算法效率
- hdu 5172 GTY's gay friends(线段树+前缀和)
- 适配器模式——得心应手的“粘合剂”
- iOS开发从入门到精通--开关按钮UISwitch控件
- 整理前段各种验证
- (高级篇)jQuery学习之jQuery Ajax用法详解
- UVa 471 - Magic Numbers
- PAT1010 一元多项式求导
- wi10优化
- Longest Substring Without Repeating Characters
- Qt基于FFmpeg播放本地 H.264(H264)文件
- adapter如何finish activity
- Android studio value 2 (com.android.dex.DexException:资源重复引用或者加载问题)
- pthread_mutex_t
- 在 Linux 上使用 VirtualBox 的命令行管理界面
- 大理石在哪?(Where is the Marble?,UVa 10474)
- 在 Linux 上使用 VirtualBox 的命令行管理界面
- dTree组件的学习
- Disruptor 详解
- C语言putenv()函数:改变或增加环境变量