ZOJ 3802 Easy 2048 Again(状压DP+位运算)【一维状压类模板--2048】

来源:互联网 发布:小米平板2怎么关闭优化 编辑:程序博客网 时间:2024/06/08 17:38

Dark_sun knows that on a single-track road (which means once he passed this area, he cannot come back again), there are some underground treasures on each area of the road which has the value of 2, 4, 8 or 16. Dark_sun can decide whether to dig them or not in order to get the highest score. The calculation rule of the total score is similar to the game Flappy 2048.

Dark_sun's bag is like a queue. When he gets a treasure, the treasure will be pushed back into the end of the bag. And the score will add the value of the treasure. For example, when there are treasures on the road in the order of {2, 8, 4, 8} and if Dark_sun decides to dig all of them, he will get the final score of 2+8+4+8=22. And his bag will finally become the sequence of {2, 8, 4, 8}.

If the adjacent treasures in the Dark_sun's bag have the same value, they will mix into a bigger treasure which has the value of their sum (the double value of the previous one). And Dark_sun will get a combo score of the value of bigger treasure. For example in the previous case, if Dark_sun decides to dig only the {2, 8, 8} treasure in sequence. He will get the basic score of 18(2+8+8). And when the last treasure (value 8) is pushed back into his bag, his bag will turn {2, 8, 8} into {2, 16} and he will get a bonus score of 16. And his final score will become 18+16=34 (which is the best strategy in this case.)

Notice that the treasures mix to the bigger one automatically when there are the same adjacent treasures. For example, when there are treasures of {2, 2, 4, 8, 16} on the road, and if Dark_sun decides to dig all of them, he will get the basic score of 32(2+2+4+8+16) and a bonus score of 60(4+8+16+32). At last he will get the total score of 92 and the bag becomes {32}.

Now, Dark_sun wants to get the highest score (no matter what's the treasure in his bag), can you tell him the what's the highest score?

Input

The first line is an integer n, which is the case number. In each case, the first line is an integer L, which is the length of the road.(0 < L ≤ 500) The second line contains L integers which can only be 2, 4, 8 or 16. This means the value of treasure on each area of the road.

Output

For each case, you should output an integer. The answer is the maximum of the total score which Dark_sun may get.

Sample Input
342 8 4 852 2 4 8 1688 4 4 2 8 4 2 2
Sample Output
3492116
Hint

In the third sample case, Dark_sun will choose {8,4,4,8,4,2,2}. Firstly, the first three treasures will be combined to 16 and then the {16,8,4,2,2} will become 32. And he will get the basic score 32(8+4+4+8+4+2+2) and the bonus score 84(8+16+4+8+16+32).

 

 【题解】 这是一道2048的状态压缩DP经典题,题意是给出n个数,每个数只可能是2,4,8,16中的一个,你可以合并其中相同的数,得分数就是合并后的数值,要求计算出最高得分。


 状态压缩方面还比较水,一开始没看出来,比完看人家的博客才知道要用状压,其实往简单了想就是每个数都只有两种可能。取或者不取,取记为1,不取就是0,这是状态,然后总共不超过500个数,往大了算每个数都取16,总共也才8000多,小于2^13,所以就可以用二进制位来表示每个数取或者不取,遍历所有情况后取最大值就好。

 【AC】

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=505;int m,n;int a[N];int dp[2][10000];//两个状态 int ans;int max(int x,int y){    return x>y?x:y;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i=1;i<=n;i++)            scanf("%d",&a[i]);        memset(dp,-1,sizeof(dp));        dp[0][0]=0;        int pos=1;        ans=0;        for(int i=1;i<=n;++i)        {            for(int j=0;j<4096*2;++j)//遍历所有情况            {                if(dp[pos^1][j]==-1) continue; //未达到该状态                dp[pos][j] = max(dp[pos^1][j],dp[pos][j]);//该数取或者不取的最大得分                ans=max(dp[pos][j],ans);//最终得分的最大值                int aa=a[i]-1;//前面所有取的状态                int t=j;                int sum=a[i];                if((t&aa)==0)                {                    int k=a[i];                    while(t&k)                    {                        sum+=k<<1;//得分                        k<<=1;                    }                    t&=~(k-1);                    t|=k;                }                else                {                    t=a[i];                }                dp[pos][t]=max(dp[pos^1][j]+sum,dp[pos][t]);                ans=max(dp[pos][t],ans);            }            pos^=1;        }        printf("%d\n",ans);    }    return 0;}
接触状态压缩不久,还有得地方比较生,正在努力中......


原创粉丝点击