现在的位置: 首页 > 综合 > 正文

ZOJ 3802

2017年11月21日 ⁄ 综合 ⁄ 共 1464字 ⁄ 字号 评论关闭

先mark一下,感觉自己好难理解。。。。正在理解中,,,,

**************************************************

几乎折腾了一下午。。。表示很痛苦。不过终于有了点理解,虽然代码可能基本就是和别人一样的了。。。。。

不过也算是学习的过程吧。。。。

然后我多打几遍在理解一下再来更新。。。。。。

*************************************************

看了好多题解,终于有了点眉目。

DP[I][J]表示前i个数中,j状态下可以得到的最大值。因为可能会爆内存,所以用了滚动数组。然后j状态存储的实际上是当前状态递减的序列,用二进制表示。因为如果当前数组末尾没有递减的数列,那么就算合并也不能再继续合并了,所以这样处理。

原先一直不理解为什么每次DP的时候要枚举到最大值,或者说不知道怎么枚举上一次得到的(剩下的)容量。然后这次好像又懂了一点点。。。如果原先出现过这样的情况,那么等到下次你枚举到这个情况的时候就会再次碰到他,这也是为什么要枚举到最大值。

DP方程用了两次,第一次是不取当前的a[i],取了当前状态的最大值。然后假设取了当前的a[i],然后看看可以合并多少次,算出得到的奖励和合并后的状态。

第二次表示合并后的那种状态是由原先某种路径得来的比较好,还是由这一次经过以上方式合并得来的比较好。

/*
3
4
2 8 4 8
5
2 2 4 8 16
8
8 4 4 2 8 4 2 2
*/
#include <stdio.h>
#include <string.h>
#define maxn 5000
int n,dp[2][maxn],a[maxn],sum,score[maxn];
int max(int x,int y)
{
    if(x>y) return x;
    else return y;
}
void solve()
{
    int i,j,k;
    int pre=0,now=1;
    dp[pre][0]=0;
    for(i=0;i<n;i++)
    {
        for(j=0;j<=4096;j++)
        {
            if(dp[pre][j]!=-1)
        {
            dp[now][j]=max(dp[now][j],dp[pre][j]);
            int t=j;
            k=a[i]-1;
            int tmp=(1<<k)-1;
            int get=score[a[i]];
            if((tmp&t)==0)
            {
                while(t&(1<<k))
                {
                    get+=score[k+2];
                    k++;
                }
                tmp=(1<<k)-1;
                t&=~tmp;///把比k低的位数全变成0
                t|=1<<k;
            }
            else t=1<<k;
            dp[now][t]=max(dp[now][t],dp[pre][j]+get);
      //     printf("**%d\n",get);
        }
        }
        now=!now;
        pre=!pre;
    }
    for(i=0;i<=4096;i++) sum=max(sum,dp[pre][i]);
}
int main()
{
    int t;
    int loc[20];
    scanf("%d",&t);
    loc[2]=1;loc[4]=2;loc[8]=3;loc[16]=4;
    score[0]=1;
    for(int i=1;i<=4096;i++)
        score[i]=score[i-1]*2;
    while(t--)
    {
        scanf("%d",&n);
        sum=0;
        memset(dp,-1,sizeof(dp));
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            a[i]=loc[a[i]];
        }
        solve();
        printf("%d\n",sum);
    }
    return 0;
}

【上篇】
【下篇】

抱歉!评论已关闭.