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] 最短Hamilton路徑(模板題+狀壓dp)
- HDU 1074 Doing Homework(狀壓DP)
- 簡易狀態壓縮DP
- 狀壓DP基礎入門
- Public Easy Round #2 E. 2048
- 合理安排(狀壓dp,包括技巧)
- NOI2001 炮兵陣地(狀壓dp)
- E - Remove Pairs(狀壓dp+博弈論)REMAI
- HDU 5816 Hearthstone(狀態壓縮DP+概率)
- Luogu P1777 幫助 題解 [ 紫 ] [ 線性 dp ] [ 狀壓 dp ]
- hdu--5418Victor and World+狀態壓縮DP
- 分組(狀壓dp+技巧:快速列舉子集)
- Codeforces 11D A Simple Task 題解 [ 藍 ] [ 狀壓 dp ]
- bzoj4145: [AMPPZ2014]The Prices(狀態壓縮+Dp)
- 【訓練題19:概率DP】One Person Game | ZOJ3329GAM
- 百練4124:海賊王之偉大航路(狀壓DP)
- 一類哈密頓路徑/迴路為背景的狀壓dp
- CF79D Password (差分+狀壓 dp+最短路/bfs)
- zoj
- [狀壓dp]leeccode1434:每個人戴不同帽子的方案數(hard)
- 動態規劃——用二進位制表示集合的狀態壓縮DP動態規劃
- 『杭電1848』Fibonacci again and againAI
- ACM-ICPC 2018 南京賽區網路預賽__E AC Challenge【狀態壓縮+DP】ACM
- HDU 1848 Fibonacci again and again(SG函式)AI函式
- 狀態壓縮
- ZOJ Monthly, March 2018
- ZOJ 3732 Graph ReconstructionStruct
- Diablo III ZOJ - 3769
- ZOJ - 2112 Dynamic Rankings
- 互不侵犯 (狀壓)
- Decade counter againAI
- HDU 1848 Fibonacci again and again (尼姆博弈+sg函式)AI函式
- ZOJ4043 : Virtual Singers
- If I were a boy againAI
- Trees and XOR Queries AgainAI
- vue實現2048Vue
- dp 套 dp(dp of dp)小記