ZOJ 3802 Easy 2048 Again ( 状态压缩 )

2015-01-27 09:57:37 · 作者: · 浏览: 12

题目链接~~>

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

解题思路:

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

代码:

#include
  
   
#include
   
     #include
     #include
     
       #include
      
        #include
       
         #include
        
          #include
         
           #include
          
            #include
           
             #include
            
              #include
             
               #include
              
                #include
               
                 #include
                
                  #include
                 
                   #include
                  
                    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<
                   
                     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 ; }