题意:
儿子和爸爸选牌, 每一次每个人只能从最左边选择或者在最右边选择, 儿子的决策是 选左边 和 右边最大的那个位置, 如果一样大, 选择左边, 爸爸的决策是为了让儿子赢, 问你 如果儿子能赢 爸爸与儿子的最小分数差是多少, 如果无论如和 爸爸都赢儿子 输出The child will be unhappy...
思路:
很乱搞的一个题目。。
我们先预处理出两个dp 来, dp1[i][j]表示 i~j 这个区间 儿子先手 爸爸拿牌的最小值,
dp2[i][j] 则表示i~j 这个区间儿子先手, 爸爸拿牌的最大值。
有了两个dp 就可以搜索了。
dfs(l,r,dif) 表示搜索l~r 这个区间, 目前爸爸减儿子的分数为dif。
然后dfs里模拟儿子和爸爸就行了, 儿子直接按照贪心来, 爸爸 的话 就都搜一遍。
dfs里得加点剪枝。
如果目前dif + dp1(最小值) >= 0 的话, 肯定是爸爸赢儿子了 return掉。
如果dif + dp2 还不如 ans(目前最优解), 也剪掉。
如果选择dp2 还小于0 就更新一下答案, 也没必要继续搜了。
当然感觉这些都没啥卵用。。
加一个小黑科技, 看到快超时时, 直接return好了。
if (clock() - ST > LIM) {
return;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <time.h>
using namespace std;
const int maxn = 100;
const int inf = 0x3f3f3f3f;
int a[maxn];
int dp1[maxn][maxn], dp2[maxn][maxn], sum[maxn];
int ST;
int LIM = 0 * CLOCKS_PER_SEC;
int DP1(int l,int r){
int& ans = dp1[l][r];
if (ans != -1) return ans;
if (l > r) {
return ans = 0;
}
if (a[l] >= a[r]){
ans = min(DP1(l + 1, r - 1) + a[r], DP1(l + 2, r) + a[l + 1]);
}
else {
ans = min(DP1(l+1, r-1) + a[l], DP1(l, r-2) + a[r-1]);
}
return ans;
}
int DP2(int l,int r){
int& ans = dp2[l][r];
if (ans != -1) return ans;
if (l > r) {
return ans = 0;
}
if (a[l] >= a[r]){
ans = max(DP2(l + 1, r - 1) + a[r], DP2(l + 2, r) + a[l + 1]);
}
else {
ans = max(DP2(l+1, r-1) + a[l], DP2(l, r-2) + a[r-1]);
}
return ans;
}
int ans;
void dfs(int l,int r,int dif){
if (l > r){
ans = max(ans, dif);
return;
}
if (dif + 2 * dp1[l][r] - (sum[r] - sum[l-1]) >= 0) return;
if (dif + 2 * dp2[l][r] - (sum[r] - sum[l-1]) <= ans) return;
if (dif + 2 * dp2[l][r] - (sum[r] - sum[l-1]) < 0){
ans = max(ans, dif + 2 * dp2[l][r] - (sum[r] - sum[l-1]));
return;
}
if (clock() - ST > LIM) { /// 醉了。。
return;
}
if (a[l] >= a[r]){
dfs(l + 1, r - 1, dif + a[r] - a[l]);
dfs(l + 2, r, dif + a[l + 1] - a[l]);
}
else {
dfs(l, r - 2, dif + a[r-1] - a[r]);
dfs(l + 1, r - 1, dif + a[l] - a[r]);
}
}
int main(){
int n;
while(~scanf("%d", &n)){
for (int i = 1; i <= n; ++i){
scanf("%d", a + i);
sum[i] = sum[i-1] + a[i];
}
ST = clock();
memset(dp1,-1,sizeof dp1);
memset(dp2,-1,sizeof dp2);
DP1(1, n); DP2(1, n);
ans = -inf;
dfs(1, n, 0);
ans = -ans;
if (ans >= inf){
puts("The child will be unhappy...");
}
else {
printf("%d\n", ans);
}
}
return 0;
}
happy happy happy
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 530 Accepted Submission(s): 157
The child takes first and the person who gets more grade wins. The child will be happy only when he wins the game.
Bob wants to make the child happy, please help him calculate the minimal difference of their grades when he loses the game.
For each test case:
the first line only contains a number n ( 1≤n≤90&&n%2==0 )
The second line contains n integers: a1,a2…an(1≤ai≤105) .
4 2 1 5 3 2 2 2
5 The child will be unhappy...