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]]); }