題目鏈接
90 Points:智障的區間 DP……設 dp[i][j] 表示區間 [i, j] 能取的最大價值,但我還是 sd 地開了第三維表示先取還是后取的價值。
交上去以為能 A,結果 #2 開心地 MLE……一看內存,64MB(把評測機吊起來打一頓)……
100 Points:有些神仙……區間 DP 的滾動數組,dp[i] 表示以 i 為首的區間得到的最大價值。
換一種思路,定義 dp[l][r] 為在區間 [l,r] 先手的人能取到的最大值,區間的長度每加 1,先手就會互換一次,為了讓這一次的先手更大,就要讓上一次更小,于是得到:
斜著滾掉一維……dp[i] 為從 i 到 i + l - 2 區間最優解:
放上代碼。
90 分:
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;const int maxn = 5000 + 10;
int n, c[maxn], dp[maxn][maxn][2];int main(int argc, const char *argv[])
{freopen("..\\nanjolno.in", "r", stdin);freopen("..\\nanjolno.out", "w", stdout);scanf("%d", &n);for(int i = 1; i <= n; ++i) scanf("%d", &c[i]), dp[i][i][0] = c[i];for(int i = 1; i < n; ++i)dp[i][i + 1][0] = max(c[i], c[i + 1]), dp[i][i + 1][1] = min(c[i], c[i + 1]);for(int i = 3; i <= n; ++i) {for(int l = 1; l <= n - i + 1; ++l) {int r = l + i - 1;if( c[l] + dp[l + 1][r][1] > c[r] + dp[l][r - 1][1] )dp[l][r][0] = c[l] + dp[l + 1][r][1], dp[l][r][1] = dp[l + 1][r][0];else dp[l][r][0] = c[r] + dp[l][r - 1][1], dp[l][r][1] = dp[l][r - 1][0];}}printf("%d %d\n", dp[1][n][0], dp[1][n][1]);fclose(stdin), fclose(stdout);return 0;
}
100 分:
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;const int maxn = 5000 + 10;
int n, c[maxn], dp[maxn];int main(int argc, const char *argv[])
{freopen("..\\nanjolno.in", "r", stdin);freopen("..\\nanjolno.out", "w", stdout);scanf("%d", &n);for(int i = 1; i <= n; ++i) scanf("%d", &dp[i]), c[i] = c[i - 1] + dp[i];for(int i = 2; i <= n; ++i) {for(int l = 1; l <= n - i + 1; ++l) {int r = l + i - 1;dp[l] = c[r] - c[l - 1] - min(dp[l], dp[l + 1]);}}printf("%d\n", dp[1]);fclose(stdin), fclose(stdout);return 0;
}
—— 月光 委身依賴
紅蓮 徹骨清明
殘留余韻 是抗爭 徒留其名