Easy 2048 Again - ZOJ 3802 像缩进dp

Easy 2048 Again


Time Limit: 2 Seconds      Memory Limit: 65536 KB



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

3
4
2 8 4 8
5
2 2 4 8 16
8
8 4 4 2 8 4 2 2

Sample Output

34
92
116

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).

题意:对于一个序列,你能够按顺序选或不选一些数。然后放在一个栈里。假设两个一样的数在一起就会合并,你的得分是放的数加上合并成的数的总和,问最后得分最多是多少。

思路:状压dp,这道题本身就是二进制,也就方便了,注意要用滚动数组。不然会爆MLE。

这里用滚动数组记录你在选第n个数的时候之前的状压情况和得分。

AC代码例如以下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
map<ll,ll> match[2];
ll F[1000010][2];
int vis[1000010];
ll ans;
void solve(ll S,ll k,int pos,int pos2)
{ F[0][pos2]++;
  F[F[0][pos2]][pos2]=S; //不选这个数,保留原状压情况
  match[pos2][S]=max(match[pos2][S],match[pos][S]);
  if((S%k)!=0) //选这个数。而且之前状压情况有比k小的数。比方之前的状压结果为8 4 2 这时你增加一个4,那么队列里面就会是 8 4 2 4,
               //前三个数都不可能再去合并了。所以状压结果仅仅要保留k就能够了
  { match[pos2][k]=max(match[pos2][k],match[pos][S]+k);
    F[0][pos2]++;
    F[F[0][pos2]][pos2]=k;
    ans=max(ans,match[pos2][k]);
    return;
  }
  ll ret=k,S2=S;
  while((S&k)!=0) //合并同样的数
  { S-=k;
    k*=2;
    ret+=k;
  }
  S+=k;
  match[pos2][S]=max(match[pos2][S],match[pos][S2]+ret);
  ans=max(ans,match[pos2][S]);
  F[0][pos2]++;
  F[F[0][pos2]][pos2]=S;
}
int main()
{ int t,n,i,j,k,len,a,b,pos=0;
  scanf("%d",&t);
  while(t--)
  { scanf("%d",&n);
    match[0].clear();match[1].clear();
    F[0][0]=1;F[1][0]=0;
    match[0][0]=0;
    ans=0;
    for(i=1;i<=n;i++)
    { pos++;
      scanf("%lld",&k);
      if(i&1)
      { a=0;b=1;}
      else
      { a=1;b=0;}
      match[b].clear();
      F[0][b]=0;
      for(j=1;j<=F[0][a];j++) // F[0][a]记录之前有多少种情况
       if(vis[F[j][a]]!=pos)
       { solve(F[j][a],k,a,b); //对之前状压结果为F[j][a]的情况考虑选或不选这个数的结果
         vis[F[j][a]]=pos;
       }
    }
    printf("%lld\n",ans);
  }
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-10-08 14:50:41

Easy 2048 Again - ZOJ 3802 像缩进dp的相关文章

ZOJ3802 Easy 2048 Again (状压DP)

ZOJ Monthly, August 2014 E题 ZOJ月赛 2014年8月 E题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5334 Easy 2048 Again Time Limit: 2 Seconds      Memory Limit: 65536 KB Dark_sun knows that on a single-track road (which means once he passed this

ZOJ 3802 Easy 2048 Again 状压DP

直接从前往后DP,因为一共只有500个数,所以累加起来的话单个数不会超过4096,并且因为是Flappy 2048的规则,所以只有之后数列末尾一串递减的是有效的,因此可以状压. 1700ms = =,据说用滚动数组优化一下会好很多 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector>

ZOJ 3802 Easy 2048 Again 状态DP

zoj 上次的月赛题,相当牛的题目啊,根本想不到是状态压缩好吧 有个预先要知道的,即500个16相加那也是不会超过8192,即,合并最多合并到4096,只有2的12次方 所以用状态压缩表示前面有的序列组合,找到了符合的,就往上累加合并生成新状态,否则就添加到前面的状态的后面构成新状态,因为每一个的状态都由前一个所得,用滚动数组即可 #include <iostream> #include <cstdio> #include <cstring> #include <

ZOJ 3802 Easy 2048 Again ( 状态压缩 )

题目链接~~> 做题感悟:这题很经典 ,需要模拟一下找规律,还是那句话遇到题自己应该手动推一下. 解题思路: 这题如果手动推几组数据的话就应该发现 ,如果放进队列的元素是递减的话,这样才可以连续合并,如果队列中有 a  ,b , a < b 那么 a 前面的必定不会与 b 经过合并再合并,因为越合并越大,so ~> 队列中最多才存 12 个数,可以用状态压缩压缩一下.注意要用滚动数组,不用可能超时. 代码: #include<iostream> #include<sst

zoj3802:easy 2048 again(状压dp)

zoj月赛的题目,非常不错的一个状压dp.. 题目大意是一个一维的2048游戏 只要有相邻的相同就会合并,合并之后会有奖励分数,总共n个,每个都可以取或者不取 问最终得到的最大值 数据范围n<=500 , a[i]={2,4,8,16}: 分析: 首先明确一下自动合并的意思,比如原有 8,4,2,进入一个2 就会变成16 所以我们需要记录前面的所有数字..计算了一下发现最大情况,500个16会合成4096 =2^12 显然全部记录是不可能的.那么怎么处理呢 我们发现,只有递减的序列才有可能向前合

Easy 2048 Again(状压dp)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3802 题意: 从数列A中, 删除若干个数(可以0个), 是删除后的数列, 进行类似  Flappy 2048 游戏的运算, 使结果最大, 求该最大值. 题解: 每个数ai, 取或不取, 满足 可用二进制表示. 当 ai < a[i + 1] 是, 易想到 如果两个数都取, ai 将不会在合并. 所以只需考虑ai[i + 1] 前的 降序列即可 .如果没个数都为1

[ACM] ZOJ 3725 Painting Storages (DP计数+组合)

Painting Storages Time Limit: 2 Seconds      Memory Limit: 65536 KB There is a straight highway with N storages alongside it labeled by 1,2,3,...,N. Bob asks you to paint all storages with two colors: red and blue. Each storage will be painted with e

ZOJ 3306 状压dp

转自:http://blog.csdn.net/a497406594/article/details/38442893 Kill the Monsters Time Limit: 7 Seconds Memory Limit: 32768 KB In order to celebrate the 8th anniversary of ZOJ, watashi introduces a strange game to other ZJU ACM team members. The board of

Food Delivery ZOJ - 3469 (区间dp)

Food Delivery ZOJ - 3469 题意:快递员送外卖,n个客户,起始位置为x,速度为v,每个客户单位时间不满意度增加hi,问最少增加多少不满意度. 每一个客户可能是从左侧送到或者从右侧送到. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int maxn=1010; 5 const int inf=0x3f3f3f3f; 6 i