• Easy 2048 Again(状压dp)


    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3802

    题意: 从数列A中, 删除若干个数(可以0个), 是删除后的数列, 进行类似  Flappy 2048 游戏的运算, 使结果最大, 求该最大值。

    题解: 每个数ai, 取或不取, 满足 可用二进制表示。 当 ai < a[i + 1] 是, 易想到 如果两个数都取, ai 将不会在合并。 所以只需考虑ai[i + 1] 前的 降序列即可 .如果没个数都为16, 合并后的数列的最大值为4026 = 2^12。 也就是说, a[i + 1]最多只需考虑 合并到a[i +1]为后的前 12项。

    具体的看 代码吧

     1 /***Good Luck***/
     2 #define _CRT_SECURE_NO_WARNINGS
     3 #include <iostream>
     4 #include <cstdio>
     5 #include <cstdlib>
     6 #include <cstring>
     7 #include <string>
     8 #include <algorithm>
     9 #include <stack>
    10 #include <map>
    11 #include <queue>
    12 #include <vector>
    13 #include <set>
    14 #include <functional>
    15 #include <cmath>
    16 
    17 #define Zero(a) memset(a, 0, sizeof(a))
    18 #define Neg(a)  memset(a, -1, sizeof(a))
    19 #define All(a) a.begin(), a.end()
    20 #define PB push_back
    21 #define inf 0x3f3f3f3f
    22 #define inf2 0x7fffffffffffffff
    23 #define ll long long
    24 using namespace std;
    25 //#pragma comment(linker, "/STACK:102400000,102400000")
    26 
    27 const int mw = 1 << 13;
    28 int n;
    29 int arr[mw]; // 滚动数组
    30 int mx;
    31 inline int add(int i, int v) {
    32     int tmp = ((i + v) | i) - i ;   
    33     int ans = v;
    34     while (v < tmp) {
    35         ans = ans + (v <<= 1);
    36     }
    37     return ans;
    38 }
    39 void cal(int v) {
    40     int tmpv;
    41     int tmpmx  = 0;
    42     for (int i = mx; i >= 0; --i) {  //mx 记录每次cal 时, 改动的最大值。 (不知为什么, 没优化这一步, 超时, 优化后 10ms,相差好大)
    43         if ((i & (v - 1))) { 
    44             tmpmx = max(tmpmx, arr[i]);  // 记录 arr[i + 1] > arr[i]中的多种情况 下的最大得分。
    45             continue;
    46         }
    47         if (arr[i] && arr[i + v] < arr[i] + (tmpv = add(i,v))) { // 计算并更新arr[i + 1] <= arr[i]中多种情况
    48             arr[i + v] = arr[i] + tmpv;
    49             mx = max(i + v, mx);         // 记录该次运行时所用的最大 数。
    50         }
    51     }
    52     arr[v] = v + tmpmx;
    53     mx = max(v, mx);
    54 }
    55 
    56 int main() {
    57     int T;
    58     scanf("%d", &T);
    59     while (T--) {
    60         Zero(arr);
    61         int val = 0;
    62         scanf("%d", &n);
    63         scanf("%d", &val);
    64         mx = val;         //第一次的范围
    65         cal(val);
    66         for (int i = 2; i <= n; ++i) {
    67             scanf("%d", &val);
    68             cal(val);
    69         }
    70         int ans = 0;
    71         for (int i = 0; i < mw; ++i) ans = max(ans, arr[i]);
    72         printf("%d
    ", ans);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    台州 OJ 3847 Mowing the Lawn 线性DP 单调队列
    洛谷 OJ P1417 烹调方案 01背包
    快速幂取模
    台州 OJ 2649 More is better 并查集
    UVa 1640
    UVa 11971
    UVa 10900
    UVa 11346
    UVa 10288
    UVa 1639
  • 原文地址:https://www.cnblogs.com/yeahpeng/p/3938168.html
Copyright © 2020-2023  润新知