题意: 共个格子,每个格子有相应的分数,
张卡牌,卡牌上的数字
表示可以从当前格子往后走
格,初始在一号格,自动得到一号格的分数,问选择卡牌进行走格子的方式中可获得的最大值为多少。
数据范围:,卡牌数字
,每种卡牌数量为
,保证
题解:
这种数据范围自然想到的是爆搜加剪枝。
由于最多有个状态,因为先使用一次
号牌再使用一次
号牌,与先使用一次
号牌,再使用一次
号牌是一种情况,如果重复递归的话复杂度爆炸,故想到记忆化搜索。
表示剩余
个
号牌,
个
号牌,
个
号牌,
个
号牌,当前在
号格子走到
号格子可得到的最大分数。每次记忆化一下
即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 50;
const int M = 360;
int f[N][N][N][N];
int n, m;
int cnt[5];
int v[N];
int score[M];
int dfs(int u, int a, int b, int c, int d) {
if(u == n) return score[u];
if(~f[a][b][c][d]) return f[a][b][c][d];
int res = 0;
if(cnt[1] > a) res = max(res, dfs(u + 1, a + 1, b, c, d));
if(cnt[2] > b) res = max(res, dfs(u + 2, a, b + 1, c, d));
if(cnt[3] > c) res = max(res, dfs(u + 3, a, b, c + 1, d));
if(cnt[4] > d) res = max(res, dfs(u + 4, a, b, c, d + 1));
return f[a][b][c][d] = score[u] + res;
}
int main()
{
memset(f, -1, sizeof f);
memset(cnt, 0, sizeof cnt);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &score[i]);
for(int i = 1, x; i <= m; i++) {
scanf("%d", &x);
cnt[x]++;
}
printf("%d\n", dfs(1, 0, 0, 0, 0));
return 0;
} 
京公网安备 11010502036488号