poj(1390)——Blocks

来源:互联网 发布:电子书阅读器推荐知乎 编辑:程序博客网 时间:2024/06/16 15:56

题意:

就是给你总共n个方块,然后让你每次消去一些方块,然后获得的得分是消去方块数的平方。问最后游戏结束的时候得分最大是多少?

思路:

这道题是一道记忆性动归程序,主要是那个dp的状态转移方程有点难想。。。

首先,我们记click_box(i,j,ex_len):表示的是在第j个大块之后有ex_len长度的大块(大块就是相同颜色进行合并之后的块)且j的颜色和ex_len的颜色相同时,在这种情况下将i-j以及ex_len这些方块进行消除之后所得获得分数的最大值。

然后进行推:click_box(i,j,ex_len) : ①j和ex_len大块都被消去,那么最大的得分就是click_box(i,j-1,0)+(len[j]+ex_len)^2

②j和ex_len进行合并之后,不进行消去,而是往前面去寻找是否还有和它们颜色相同的方块,并再进行合并。

然后在这两种情况下进行递归就好啦~~

至于为什么二维是不行的,因为它无法限制第二种情况。

如有理解不清楚的,欢迎指教!

#include<cstdio>#include<cstring>#include<set>#include<cmath>#include<map>#include<stack>#include<string>#include<vector>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;#define inf 99999999#define maxn 220int n;int col[maxn],res[maxn][maxn][maxn];struct node{    int co;    int len;}a[maxn];int click_box(int i,int j,int ex_len){    if(i>j) return 0;    if(res[i][j][ex_len]!=-1) return res[i][j][ex_len];    if(i==j){        res[i][j][ex_len]=((a[i].len+ex_len)*(a[i].len+ex_len));        return res[i][j][ex_len];    }    //这里不用判断j和ex_len的颜色是否相同,因为我们定义状态的时候就默认click_box(i,j,len),j的颜色是和ex_len是相同的    res[i][j][ex_len]=max(click_box(i,j-1,0)+(ex_len+a[j].len)*(ex_len+a[j].len),res[i][j][ex_len]);    for(int k=i;k<=j-2;k++){        //而在这里需要判断两个的颜色是否相同,因为这里是要判断k和a[j].len+ex_len是否能够进行合并        if(a[k].co==a[j].co)        res[i][j][ex_len]=max(res[i][j][ex_len],click_box(i,k,a[j].len+ex_len)+click_box(k+1,j-1,0));    }    return res[i][j][ex_len];}int main(){    int T;    scanf("%d",&T);    int jj=1;    while(T--){        scanf("%d",&n);        for(int i=1;i<=n;i++) scanf("%d",&col[i]);        memset(a,0,sizeof(a));        int color=-1,num=0,nn=0;        for(int i=1;i<=n;i++){            if(color==-1||col[i]==color){                num++;                color=col[i];            }            else if(col[i]!=color){                a[nn].co=color;                a[nn++].len=num;                num=1;                color=col[i];            }            if(i==n){                a[nn].co=color;                a[nn++].len=num;            }        }        memset(res,-1,sizeof(res));        int ans=click_box(0,nn-1,0);        printf("Case %d: %d\n",jj++,ans);    }    return 0;}/*291 2 2 2 2 3 3 3 111*/


0 0
原创粉丝点击