ZOJ 3802 Easy 2048 Again ( 状态压缩 )
        【摘要】   题目链接~~> 
做题感悟:这题很经典 ,需要模拟一下找规律,还是那句话遇到题自己应该手动推一下。 
解题思路: 
              这题如果手动推几组数据的话就应该发现 ,如果放进队列的元素是递减的话,这样才可以连续合并,如果队列中有 a  ,b , a < b...
    
    
    
    做题感悟:这题很经典 ,需要模拟一下找规律,还是那句话遇到题自己应该手动推一下。
解题思路:
这题如果手动推几组数据的话就应该发现 ,如果放进队列的元素是递减的话,这样才可以连续合并,如果队列中有 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 ;
     
    
 
   - 
    
     
    
    
     
      }
     
    
 
  
 
 
文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/nyist_zxp/article/details/41050259
        【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
            cloudbbs@huaweicloud.com
        
        
        
        
        
        
        - 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)