题意:给你长度为n的序列,爸爸和儿子玩一个游戏,儿子先手,儿子每次都选择最左边与最右边最大的那个拿走(若左右相等拿左边),爸爸可以任意拿最左边或者最右边。
题解:
①对于这道题n只有90,我们可以先折半,将前半段与后半段分开考虑,预处理后半段暴力结果,然后dfs(l,r,cha)(表示当前搜到区间[l,r]时候的差值)暴搜前半段情况,对于搜索到区间大小等于后半段操作长度的时候,我们对于当前差值cha在后半段预处理的结果中lower_bound最优答案。我这里选择后半段长度为32,(再长就T了= =)。
②由于前半段完全暴搜肯定爆时间,于是我们加入剪枝。
首先我们要预处理所有区间能得到的最大值差值与最小差值。之后
剪枝:①对于当前区间[l,r],假如当前差值+mindif[l,r]>=0,说明继续搜下去不可能有解,直接return;
②对于当前区间[l,r],假如当前差值+maxdif[l,r]<=ans,那说明继续做下去得到的解肯定比ans小,差值更大,也直接return;
③对于当前区间[l,r],假如当前差值+maxdif[l,r]<0,那我们直接可以更新答案,然后return;
③那接下来我们如何得到所有区间的最值呢,我们考虑dp
枚举所有区间,先将儿子的选择消去。然后考虑爸爸的转移(ll,rr为转移之后的l与r):
mindif[l][r]=min(mindif[l][r],a[ll]+mindif[ll+1][rr]-sub);
mindif[l][r]=min(mindif[l][r],a[rr]+mindif[ll][rr-1]-sub);
maxdif[l][r]=max(maxdif[l][r],a[ll]+maxdif[ll+1][rr]-sub);
maxdif[l][r]=max(maxdif[l][r],a[rr]+maxdif[ll][rr-1]-sub);
之后我们就可以得到答案了
AC代码:
#include
#include
#include
#include
#include