ZOJ 3802 Easy 2048 Again(狀壓dp)
這道題的意思就是:2048遊戲變成了只有一行的時候的玩法,可以向左合併。給你一串數字你可以選擇一些加入佇列,和為每個數的和,加上合併成的數字。
解題思路:如果一個序列可以合併那麼它一定是降序的,比如:32,16,8,4否則的話,他是不能合併的此時的和就確定了。比如32, 32, 8,16.後面的16怎麼合併都會比8大,所以是16之前的數字不可能繼續合併下去。通過分析我們可以知道降序序列最多會有12種組合。4096……2.所以每次的時候狀壓這種狀態,每個數字每次有兩個選擇,放入或者並不放入佇列當中。在放的時候在列舉前一種的狀態推到下一個狀態。
如果當前數字比上一個狀態中最小的數字小的話,就可以把這個數字加入這個狀態中,如果大那就這個狀態不會向下推出新狀態了,新狀態的開始也就是x了。(這裡狀壓的序列是降序的所以從最小的列舉就可以了。)相同就不斷的進行合併。
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 canonly 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).
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-10
///#define M 1000100
///#define LL __int64
#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)
using namespace std;
const int maxn = 510;
int dp[510][8016];
int num[maxn];
void change(int s, int ss, int k, int x)
{
if(k == 0)
{
dp[s][x] = max(dp[s][x], dp[ss][0]+x);
return;
}
if(dp[ss][k] == 0) return;
dp[s][k] = max(dp[s][k],dp[ss][k]);
int y = x;
int ans = x;
for(int i = 0; i < 13; i++)
{
int now = (1<<i);
if((k&now) == 0) continue;
if(now < y) dp[s][x] = max(dp[ss][k]+x, dp[s][x]);
if(now > y) dp[s][x+k] = max(dp[s][x+k], dp[ss][k]+ans);
if(now != y) return ;
y *= 2;
ans += y;
}
dp[s][y] = max(dp[s][y], dp[ss][k]+ans);
}
int main()
{
int T;
cin >>T;
while(T--)
{
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%d",&num[i]);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= 8000; j++) dp[i][j] = 0;
dp[1][num[1]] = num[1];
for(int i = 2; i <= n; i++)
for(int j = 0; j <= 8000; j++)
change(i, i-1, j, num[i]);
int Max = 0;
for(int i = 0; i <= 8000; i++) Max = max(dp[n][i], Max);
cout<<Max<<endl;
}
return 0;
}
相關文章
- 狀壓 dp
- 狀壓DP
- 狀壓DP基礎入門
- 合理安排(狀壓dp,包括技巧)
- Public Easy Round #2 E. 2048
- ZOJ 1013 Great Equipment(DP)UI
- E - Remove Pairs(狀壓dp+博弈論)REMAI
- HDU 4770 Lights Against Dudely(列舉所有狀態 當然壯壓dp會很簡單)AI
- ZOJ 2745 01-K Code(DP)(轉)
- Uva-1633 Dyslexic Gollum(狀壓DP)Go
- HDU 5067 Harry And Dig Machine(狀壓dp)Mac
- zoj 1093 dp Monkey and BananaNaN
- 演算法學習之路|狀態壓縮dp演算法
- bzoj 3812: 主旋律 [容斥原理 狀壓DP]
- Codeforces Round #321 (Div. 2) D 狀壓dp
- Lightoj 1021 Painful Bases (狀壓dp 有趣)AI
- 分組(狀壓dp+技巧:快速列舉子集)
- Luogu P1777 幫助 題解 [ 紫 ] [ 線性 dp ] [ 狀壓 dp ]
- NOIP2005過河[DP 狀態壓縮]
- POJ 3254 Corn Fields:網格密鋪類 狀壓dp
- Codeforces 11D A Simple Task 題解 [ 藍 ] [ 狀壓 dp ]
- POJ 2411 Mondriaan's Dream:網格密鋪類 狀壓dp
- URAL 1152 False Mirrors(簡單的狀態壓縮dp)False
- Codeforces 327E Axis Walking (狀壓dp lowbit優化)優化
- CF79D Password (差分+狀壓 dp+最短路/bfs)
- 一類哈密頓路徑/迴路為背景的狀壓dp
- Codeforces 895C Square Subsets:狀壓dp【組合數結論】
- HDU 5135 Little Zu Chongzhi's Triangles(狀壓dp或者貪心)
- HDU 1992Tiling a Grid With Dominoes(狀壓dp)
- UVA 11825 dp、狀態壓縮、二進位制法表示集合
- hdu3001 狀態壓縮dp+三進位制
- POJ1141 ZOJ1463 Brackets Sequence【區間dp】Racket
- 動態規劃——用二進位制表示集合的狀態壓縮DP動態規劃
- [狀壓dp]leeccode1434:每個人戴不同帽子的方案數(hard)
- Codeforces 453B Little Pony and Harmony Chest:狀壓dp【記錄轉移路徑】
- 互不侵犯 (狀壓)
- 2014上海網路賽1004||hdu5045 contest【狀態壓縮dp】
- ACM-ICPC 2018 南京賽區網路預賽__E AC Challenge【狀態壓縮+DP】ACM