题目链接:
http://www.sicily.3322.org/sicily/show_problem.php?pid=1176 动态规划。
设 d [ a ][ b ] 表示在区间 [ a, b ] 上,玩家 2 运用贪心策略所导致双方分数的最大差值。
递推公式:
由于玩家 1 可以任意选择在两头取数,因此要对玩家 1 每次的选择进行分类讨论。
1. 玩家 1 选择取最左边的数 array[ a ]
if (array[a + 1] >= array[b])
points1 = dp(a + 2, b) + array[a] - array[a + 1] (玩家 2 选择array[a + 1])
else
points1 = dp(a + 1, b - 1) + array[a] - array[b] (玩家 2 选择array[b])
2. 玩家 2 选择取最右边的数 array[ b ]
if (array[a] >= array[b - 1])
points2 = dp(a + 1, b - 1) + array[b] - array[a] (玩家 2 选择array[a])
else
points2 = dp(a, b - 2) + array[b] - array[b - 1] (玩家 2 选择array[b - 1])
那么,
d[a][b] = max(points1, points2)
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std;
const int oo = 100100;
int array[1100]; int d[1100][1100]; int dp(
int a, int b)
{ if (
d[a][b
] != oo)
return d[a][b
]; if (
a > b)
return 0;
if (
array[a + 1] >= array[b
] && array[a] >= array[b
- 1]) d[a][b
] = max(
dp(
a + 2, b)
+ array[a] - array[a + 1], dp(
a + 1, b
- 1)
+ array[b
] - array[a]); else if (
array[a + 1] >= array[b
] && array[a] < array[b
- 1]) d[a][b
] = max(
dp(
a + 2, b)
+ array[a] - array[a + 1], dp(
a, b
- 2)
+ array[b
] - array[b
- 1]); else if (
array[a + 1] < array[b
] && array[a] >= array[b
- 1]) d[a][b
] = max(
dp(
a + 1, b
- 1)
+ array[a] - array[b
], dp(
a + 1, b
- 1)
+ array[b
] - array[a]); else d[a][b
] = max(
dp(
a + 1, b
- 1)
+ array[a] - array[b
], dp(
a, b
- 2)
+ array[b
] - array[b
- 1]); return d[a][b
]; } int main()
{ //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int n;
int counter;
counter = 0;
while (
scanf(
"%d", &n
), n
!= 0)
{ counter ++;
for (
int i = 1;
i <= n;
i ++)
for (
int j = 1;
j <= n;
j ++)
d[i][j] = oo;
for (
int i = 1;
i <= n;
i ++)
scanf(
"%d", &array[i]); printf(
"In game %d, the greedy strategy might lose by as many as %d points.\n", counter, dp(
1, n));
} return 0;
}
评论