zoukankan      html  css  js  c++  java
  • [USACO10DEC] Treasure Chest

    题目链接

    90 Points:智障的区间 DP……设 dp[i][j] 表示区间 [i, j] 能取的最大价值,但我还是 sd 地开了第三维表示先取还是后取的价值。

    交上去以为能 A,结果 #2 开心地 MLE……一看内存,64MB(把评测机吊起来打一顿)……

    100 Points:有些神仙……区间 DP 的滚动数组,dp[i] 表示以 i 为首的区间得到的最大价值。

    换一种思路,定义 dp[l][r] 为在区间 [l,r] 先手的人能取到的最大值,区间的长度每加 1,先手就会互换一次,为了让这一次的先手更大,就要让上一次更小,于是得到:

    $ dp[l][r] = sum[r] - sum[l - 1] - min(dp[l][r - 1], dp[l + 1][r]); $

    斜着滚掉一维……dp[i] 为从 i 到 i + l - 2 区间最优解:

    $ dp[i] = sum[j] - sum[i - 1] - min(dp[i], dp[i + 1]); $

    放上代码。

    90 分:

    ```cpp #include #include #include #include #include #include using namespace std;

    const int maxn = 5000 + 10;
    int n, c[maxn], dp[maxn][maxn][2];

    int main(int argc, const char *argv[])
    {
    freopen(".. anjolno.in", "r", stdin);
    freopen(".. anjolno.out", "w", stdout);

    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) scanf("%d", &c[i]), dp[i][i][0] = c[i];
    for(int i = 1; i < n; ++i)
    dp[i][i + 1][0] = max(c[i], c[i + 1]), dp[i][i + 1][1] = min(c[i], c[i + 1]);
    for(int i = 3; i <= n; ++i) {
    for(int l = 1; l <= n - i + 1; ++l) {
    int r = l + i - 1;
    if( c[l] + dp[l + 1][r][1] > c[r] + dp[l][r - 1][1] )
    dp[l][r][0] = c[l] + dp[l + 1][r][1], dp[l][r][1] = dp[l + 1][r][0];
    else dp[l][r][0] = c[r] + dp[l][r - 1][1], dp[l][r][1] = dp[l][r - 1][0];
    }
    }
    printf("%d %d ", dp[1][n][0], dp[1][n][1]);

    fclose(stdin), fclose(stdout);
    return 0;
    }

    
    <h4>100 分:</h4>
    ```cpp
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 5000 + 10;
    int n, c[maxn], dp[maxn];
    
    int main(int argc, const char *argv[])
    {
      freopen("..\nanjolno.in", "r", stdin);
      freopen("..\nanjolno.out", "w", stdout);
    
      scanf("%d", &n);
      for(int i = 1; i <= n; ++i) scanf("%d", &dp[i]), c[i] = c[i - 1] + dp[i];
      for(int i = 2; i <= n; ++i) {
        for(int l = 1; l <= n - i + 1; ++l) {
          int r = l + i - 1;
          dp[l] = c[r] - c[l - 1] - min(dp[l], dp[l + 1]);
        }
      }
      printf("%d
    ", dp[1]);
    
      fclose(stdin), fclose(stdout);
      return 0;
    }
    

     —— 月光 委身依赖

        红莲 彻骨清明

        残留余韵 是抗争 徒留其名

  • 相关阅读:
    Android Studio下载及离线升级方法
    动态调用WebService
    哈哈哈 终于通过自己的努力 把这个模板上长毛的土豆去掉了
    关于“只有注册用户登录后才能阅读该文”
    SQL Server 2008 R2——根据数据查找表名和字段名 根据脏数据定位表和字段
    Windows驱动——虚拟机 虚拟串口 双机调试
    协议——如何制作一个简易的串口通信协议
    问题解决——复合检测项目的定义和使用
    算法——成语首尾接龙 成语接龙
    C++基础——函数指针 函数指针数组
  • 原文地址:https://www.cnblogs.com/nanjoqin/p/10090619.html
Copyright © 2011-2022 走看看