题意:
儿子和爸爸选牌, 每一次每个人只能从最左边选择或者在最右边选择, 儿子的决策是 选左边 和 右边最大的那个位置, 如果一样大, 选择左边, 爸爸的决策是为了让儿子赢, 问你 如果儿子能赢 爸爸与儿子的最小分数差是多少, 如果无论如和 爸爸都赢儿子 输出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
#include
#include
#include
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;
}