P1541
考虑 (DP)
首先考虑 (DP) 的状态表示:(dp[a][b][c][d]) 表示 走 (1) 格还剩 (a) 个,走 (2) 格还剩 (b) 个,走 (3) 格还剩 (c) 个,走 (4) 个还剩 (d) 个最大的权值和。
那么在当前状态下在还能走的情况下可以走一格,两格,三格,四格。
所以考虑记忆化搜索,思维难度较小。
(dp[a][b][c][d] = max(dp[a - 1][b][c][d],dp[a][b - 1][c][d],dp[a][b][c - 1][d],dp[a][b][c][d - 1])) 同时 (a geq 1,b geq 1,c geq 1,d geq 1)
当前的所在位置是 int pos = 1 + (a0 - a) + (a1 - b) * 2 + (a2 - c) * 3 + (a3 - d) * 4;
最终算出答案。
我的代码有点妖娆,大概思路就是不累加当前所在位置的权值,而是算下一个能够到达的位置的权值,这样算就少算了开始的第一个位置的值,最后要加上去。
#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define rep(I, N) for (int I = 1; I <= (N); ++I)
#define repp(I, N) for (int I = 0; I < (N); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORR(I, A, B) for (int I = (A); I >= (B); I--)
#define SORT_UNIQUE(c) (sort(c.begin(), c.end()), c.resize(distance(c.begin(), unique(c.begin(), c.end()))))
#define GET_POS(c, x) (lower_bound(c.begin(), c.end(), x) - c.begin())
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
const int N = 350 + 5;
const int M = 45;
const double eps = 1e-7;
const int mod = 1e9 + 7;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL, LL> PLL;
typedef vector<PLL> VPLL;
int ax[N], b[N];
int dp[M][M][M][M];
int a0 = 0, a1 = 0, a2 = 0, a3 = 0;
int n, m;
int dfs(int a, int b, int c, int d)
{
if (dp[a][b][c][d] != -1)
return dp[a][b][c][d];
int ans = 0;
int pos = 1 + (a0 - a) + (a1 - b) * 2 + (a2 - c) * 3 + (a3 - d) * 4;//算位置
if (a >= 1)
{
ans = max(ans, dfs(a - 1, b, c, d) + ax[pos + 1]);// (a-1,b,c,d)表示位置的权值,下同
}
if (b >= 1)
ans = max(ans, dfs(a, b - 1, c, d) + ax[pos + 2]);
if (c >= 1)
ans = max(ans, dfs(a, b, c - 1, d) + ax[pos + 3]);
if (d >= 1)
ans = max(ans, dfs(a, b, c, d - 1) + ax[pos + 4]);
return (dp[a][b][c][d] = ans);
}
int main()
{
cin >> n >> m;
rep(i, n) cin >> ax[i];
rep(i, m) cin >> b[i];
memset(dp, -1, sizeof dp);
rep(i, m)
{
if (b[i] == 1)
a0++;
else if (b[i] == 2)
a1++;
else if (b[i] == 3)
a2++;
else
a3++;
}
cout << dfs(a0, a1, a2, a3) + ax[1] << endl;//加上第一个位置的值
return 0;
}