洛谷P1541 乌龟棋

题目链接

  卡片只有四张,并且我们要知道使用完某张牌之后得到的积分,所以我们要去枚举所有的情况,因为牌的种类数比较少,所以我们可以开四维数组去暴力枚举所有的状态,并且在每一次从前一种状态走到下一个位置的时候,要及时更新,题目要求的是求出最大值这个属性,所以在转移的时候我们只需要去维护最大值这个性质就可以了,所以我们的状态转移方程就是$$dp[i] = \max (dp[i], dp[i - 1] + a[i])$$

#include <bits/stdc++.h>

using i64 = long long;

#define rep(i, a, n) for (int i = a; i < n; i ++ )
#define per(i, a, n) for (int i = n - 1; i >= a; i -- )
#define SZ(a) (int(a.size()))
#define pb push_back
#define all(a) a.begin(), a.end()
//head

constexpr int N = 1010;

int n, m;
int a[N], cnt[5];
int dp[50][50][50][50];

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i ++ ) scanf("%d", a + i);
	rep(i,0,m) {
		int x; scanf("%d", &x);
		cnt[x] ++;
	}

	dp[0][0][0][0] = a[1];
	for (int i = 0; i <= cnt[1]; i ++ )
		rep(j, 0, cnt[2] + 1)
			rep(k, 0, cnt[3] + 1)
				rep(t, 0, cnt[4] + 1) {
					int cur = 1 + i * 1 + j * 2 + k * 3 + t * 4;
					if (!i && !j && !t && !k) continue;
					if (i) dp[i][j][k][t] = std::max(dp[i][j][k][t], dp[i - 1][j][k][t] + a[cur]);
					if (j) dp[i][j][k][t] = std::max(dp[i][j][k][t], dp[i][j - 1][k][t] + a[cur]);
					if (k) dp[i][j][k][t] = std::max(dp[i][j][k][t], dp[i][j][k - 1][t] + a[cur]);
					if (t) dp[i][j][k][t] = std::max(dp[i][j][k][t], dp[i][j][k][t - 1] + a[cur]);
				}

	printf("%d\n", dp[cnt[1]][cnt[2]][cnt[3]][cnt[4]]);

	return 0;
}
posted @ 2022-05-04 00:32  浅渊  阅读(33)  评论(0)    收藏  举报