AcWing - 312 - 乌龟棋 = dp

https://www.acwing.com/problem/content/314/

注意x1<0是用的x2,x3,x4太多,直接break,而超过上界则是用得不够多,要continue。然而会爆空间,仿照滚动数组的方法进行滚动,要注意赋初值(或者直接memset也可以)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll a[355];
ll dp[5][41][41][41];
int cnt[5];

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        scanf("%lld", &a[i]);
    }
    for(int i = 1; i <= m; ++i) {
        int x;
        scanf("%d", &x);
        cnt[x]++;
    }
    dp[1][0][0][0] = a[1];
    for(int i = 2; i <= n; ++i) {
        for(int x2 = 0; x2 <= cnt[2]; ++x2) {
            if(i - 1 - 2 * x2 < 0)
                break;
            for(int x3 = 0; x3 <= cnt[3]; ++x3) {
                if(i - 1 - 2 * x2 - 3 * x3 < 0)
                    break;
                for(int x4 = 0; x4 <= cnt[4]; ++x4) {
                    int x1 = i - 1 - 2 * x2 - 3 * x3 - 4 * x4;
                    if(x1 < 0)
                        break;
                    if(x1 > cnt[1])
                        continue;
                    if(cnt[1])
                        dp[i % 5][x2][x3][x4] = dp[(i - 1) % 5][x2][x3][x4];
                    else
                        dp[i % 5][x2][x3][x4] = 0;
                    if(i >= 2 && x2)
                        dp[i % 5][x2][x3][x4] = max(dp[i % 5][x2][x3][x4], dp[(i - 2) % 5][x2 - 1][x3][x4]);
                    if(i >= 3 && x3)
                        dp[i % 5][x2][x3][x4] = max(dp[i % 5][x2][x3][x4], dp[(i - 3) % 5][x2][x3 - 1][x4]);
                    if(i >= 4 && x4)
                        dp[i % 5][x2][x3][x4] = max(dp[i % 5][x2][x3][x4], dp[(i - 4) % 5][x2][x3][x4 - 1]);
                    dp[i % 5][x2][x3][x4] += a[i];
                    //printf("i=%d x2=%d x3=%d x4=%d %lld\n", i, x2, x3, x4, dp[i][x2][x3][x4]);
                }
            }
        }
    }
    printf("%lld\n", dp[n % 5][cnt[2]][cnt[3]][cnt[4]]);
}

转载于:https://www.cnblogs.com/Inko/p/11581787.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值