Educational Codeforces Round 92 (Rated for Div. 2) B. Array Walk 动态规划
给定一个长度为n的正数组,在这个数组上跑,每跑到一个点获得该点的分数。
有k次行动的机会,有最多z次返回的机会。且返回不得连续返回两次。
k <= n - 1, 1 <= z <= min(5,k)
首先此题背景和《乌龟棋》很相似,其次z的范围很小,可以考虑dp
dp[k][z]表示当前走了k步,返回了z步。
容易想到的贪心策略是如果要返回,必然在同一个点反复横跳。
转移方程
dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] + a[i - 2 * j + 1]);
if (j < z && i + 2 <= k) dp[i + 2][j + 1] = max(dp[i + 2][j + 1], dp[i][j] + a[i - 2 * j + 1] + a[i - 2 * j]);
因此两重循环,枚举 i 0 ~ k j 0 ~ z
此题有一定难度,很有教育意义!!
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define pb push_back #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define moD 1000000003 #define pii pair<ll,ll> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second typedef long long ll; typedef unsigned long long ull; const ll MOD = 1e6 + 7; const int maxn = 1e5 +5; const double Inf = 10000.0; const double PI = acos(-1.0); using namespace std; ll mul(ll a, ll b, ll m) { ll res = 0; while (b) { if (b & 1) res = (res + a) % m; a = (a + a) % m; b >>= 1; } return res % m; } ll quickPower(ll a, ll b, ll m) { ll base = a; ll ans = 1ll; while (b) { if (b & 1) ans = mul(ans, base , m); base = mul(base, base , m); b >>= 1; } return ans; } int readint() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } ll readll() { ll x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } void Put(int x) { if (x > 9) Put(x / 10); putchar(x % 10 + '0'); } int dp[maxn][6]; int a[maxn]; void solve() { memset(dp, 0, sizeof dp); int n, k, z; n = readint(), k = readint(), z = readint(); for (int i = 0; i < n; i++) a[i] = readint(); dp[0][0] = a[0]; for (int i = 0; i < k; i++) { for (int j = 0; j <= z && 2 * j <= i; j++) { dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] + a[i - 2 * j + 1]); if (j < z && i + 2 <= k) dp[i + 2][j + 1] = max(dp[i + 2][j + 1], dp[i][j] + a[i - 2 * j + 1] + a[i - 2 * j]); } } int ans = -1; for (int i = 0; i <= z; i++) ans = max(dp[k][i], ans); Put(ans); puts(""); } int main() { int T; cin >> T; while (T--) solve(); }