zoukankan      html  css  js  c++  java
  • C. Arcade dp二维费用背包 + 滚动数组 玄学

    http://codeforces.com/gym/101257/problem/C

    询问从左上角走到右下角,每次只能向右或者向左,捡起三种物品算作一个logo,求最多能得到多少个logo。

    设dp[i][j][k][h]表示走到(i, j)这个格子,然后得到的第一种物品是k,第二种物品是h的时候,能得到的第三个物品的最大值是多少。

    -inf表示不存在这个状态,其实第三种物品可以算出来,因为一共的步数就是i + j - 1,所以捡起的物品数量是固定的。

    所以直接这样dp下去即可,是一个背包问题。

    然后会MLE,所以我把第一维滚动了。(不会把第二维也滚动,一直出不了样例)

    有一个小bug就是,每种物品最多都是可以捡200个,n + m - 1个,一定要都枚举是否成立。

    一开始我只枚举到67个,因为67 * 3 = 201,logo数目其实最多就是66

    但是会wa。还想不到数据

    可能dp应该是要遍历所有可能的结果,只不过是选最优,有一些部分被抛弃了而已。

    所以枚举到200吧,毕竟它最多能捡起200个。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    const int maxn = 1e2 + 2;
    char str[maxn][maxn];
    int n, m;
    int dp[4][maxn][200 + 2][200 + 2];
    int pre(int id) {
        if (id == 0) return 2;
        else return id - 1;
    }
    void work() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) {
            scanf("%s", str[i] + 1);
        }
        memset(dp, -0x3f, sizeof dp);
        dp[0][1][0][0] = 0;
        dp[1][0][0][0] = 0;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                int en = i + j - 1;
                for (int k = en; k >= 0; --k) {
                    for (int h = en; h >= 0; --h) {
                        dp[i % 3][j][k][h] = -inf;
                        if (str[i][j] == '>') {
                            if (k < 1) {
                                dp[i % 3][j][k][h] = -inf;
                                continue;
                            }
                            dp[i % 3][j][k][h] = dp[pre(i % 3)][j][k - 1][h];
                            dp[i % 3][j][k][h] = max(dp[i % 3][j][k][h], dp[i % 3][j - 1][k - 1][h]);
                        } else if (str[i][j] == '|') {
                            if (h < 1) {
                                dp[i % 3][j][k][h] = -inf;
                                continue;
                            }
                            dp[i % 3][j][k][h] = dp[pre(i % 3)][j][k][h - 1];
                            dp[i % 3][j][k][h] = max(dp[i % 3][j][k][h], dp[i % 3][j - 1][k][h - 1]);
                        } else {
                            dp[i % 3][j][k][h] = dp[pre(i % 3)][j][k][h] + 1;
                            dp[i % 3][j][k][h] = max(dp[i % 3][j][k][h], dp[i % 3][j - 1][k][h] + 1);
                        }
                    }
                }
            }
        }
        int ans = 0;
        for (int i = 0; i <= 200; ++i) {
            for (int j = 0; j <= 200; ++j) {
                ans = max(ans, min(i, min(j, dp[n % 3][m][i][j])));
    //            if (dp[n % 3][m][i][j] >= 0) {
    //                cout << i << " " << j << " " << dp[n % 3][m][i][j] << endl;
    //            }
            }
        }
        cout << ans << endl;
    
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    route命令基本使用
    Linux提权(capabilities)
    shell编程(case)
    VMware镜像迁移至zstack
    VMware安装zstack踩坑日记
    wordpress添加https
    python下载油管视频
    pandas多班级合并提取教师个人课表,多表同位置填充数据
    博客园美化备份
    Linux 运行Python文件/命令/程序,不因终端关闭而终止运行
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6417357.html
Copyright © 2011-2022 走看看