ZOJ 3802 Easy 2048 Again ( 状态压缩 )

题目链接~~>

做题感悟:这题很经典 ,需要模拟一下找规律,还是那句话遇到题自己应该手动推一下。

解题思路:

这题如果手动推几组数据的话就应该发现 ,如果放进队列的元素是递减的话,这样才可以连续合并,如果队列中有 a  ,b , a < b 那么 a 前面的必定不会与 b 经过合并再合并,因为越合并越大,so ~> 队列中最多才存 12 个数,可以用状态压缩压缩一下。注意要用滚动数组,不用可能超时。

代码:

#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std  ;
#define INT __int64
#define L(x)  (x * 2)
#define R(x)  (x * 2 + 1)
const int INF = 0x3f3f3f3f ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int mod = 1000000007 ;
const int MY = (1<<13) + 5 ;
const int MX = 500 + 5 ;
const int MS = 13 ;
int n ;
int g[MX] ,dp[2][MY] ;
int main()
{
    int Tx ;
    scanf("%d" ,&Tx) ;
    while(Tx--)
    {
        scanf("%d" ,&n) ;
        for(int i = 1 ;i <= n ; ++i)
            scanf("%d" ,&g[i]) ;
        memset(dp ,-1 ,sizeof(dp)) ;
        dp[0][0] = 0 ;
        for(int i = 1 ;i <= n ; ++i)
          for(int S = 0 ;S <= MY ; ++S)
            if(dp[(i-1)%2][S] != -1) // 由前一行的合法状态递推第 i 行
            {
                dp[i%2][S] = max(dp[i%2][S] ,dp[(i-1)%2][S]) ;   // 不拿
                int k ,key ,sum ,ret ,temp ;
                if(S)
                {
                    for(int k = 0 ;k <= 12 ; ++k)     // 计算队列中的最小的元素
                      if(S&(1<<k))
                      {
                         temp = (1<<k) ;
                         break ;
                      }
                }
                else   temp = 0 ;
                if(temp < g[i])              // 无法合并
                    dp[i%2][g[i]] = max(dp[i%2][g[i]] ,dp[(i-1)%2][S] + g[i]) ;
                else if(temp == g[i])  // 可以合并
                {
                    key = S ; sum = g[i] ;  ret = g[i] ;
                    while(key&ret)
                    {
                        sum += ret*2 ;
                        key = key - ret ;
                        ret <<= 1 ;
                    }
                    dp[i%2][key+ret] = max(dp[i%2][key+ret] ,dp[(i-1)%2][S] + sum) ;
                }
                else if(temp > g[i])  // 放入队列
                    dp[i%2][g[i] + S] = max(dp[i%2][g[i] + S] ,dp[(i-1)%2][S] + g[i]) ;
            }
        int ans = 0 ;
        for(int S = 0 ;S <= MY ; ++S)
           ans = max(ans ,dp[n%2][S]) ;
        printf("%d\n" ,ans) ;
    }
    return 0 ;
}
时间: 2024-12-23 21:25:48

ZOJ 3802 Easy 2048 Again ( 状态压缩 )的相关文章

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 状压DP

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

zoj 3471 Most Powerful(状态压缩dp)

Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way every two at

[ZOJ 3662] Math Magic (动态规划+状态压缩)

先贴代码,晚上回去说 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <cmath> 5 #include <map> 6 #include <iterator> 7 #include <vector> 8 using namespace std; 9 typedef long long LL; 10 11 int n,m

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 th

ZOJ 1639 Hang Up the System (状态压缩)

Hang Up the System Time Limit: 2 Seconds      Memory Limit: 32768 KB You're going to design a multi-task operating system for an embedded system. Because the resources are limited on this mini computer, parallel running of some programs will probably

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

Codeforces544E:Remembering Strings(状态压缩)

You have multiset of n strings of the same length, consisting of lowercase English letters. We will say that those strings are easy to remember if for each string there is some position i and some letter c of the English alphabet, such that this stri

ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))

求一条蛇到(1,1)的最短路长,题目不简单,状态较多,需要考虑状态压缩,ZOJ的数据似乎比POj弱一些 POJ1324(ZOJ1361)-Holedox Moving 题意:一条已知初始状态的蛇,求其到(1,1)的最短路长 题解:开始做的时候用BFS暴力做了一次,结果RE了,后来看了其他的题解和discuss才转向状态压缩.也看到有人用A*做出来了. 现在简要介绍一下状态压缩的思路: 由于蛇身最长只有8,可以利用两条相邻蛇身坐标确定其相对方向(四个方向),两位二进制可以表示 这样 一个蛇头坐标+