HDU 6196 happy happy happy [折半暴搜+剪枝+DP]
来源:互联网 发布:淘宝食品类目 编辑:程序博客网 时间:2024/06/05 10:43
题意:给你长度为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<stdio.h>#include<vector>#include<string.h>#include<algorithm>#include<map>#include<time.h>#define N 95using namespace std;int a[N];vector<int>vt[N];vector<int>::iterator it;int mi[N][N],ma[N][N];int ans,n,hou;map<int,int>mp;void init() { for(int i=0;i<N;i++)for(int j=i;j<N;j++){mi[i][j]=(int)1e9;ma[i][j]=(int)-1e9;} for(int l=n;l>=1;--l) { for(int r=l;r<=n;++r) { int ll=l,rr=r; int sub; if(a[ll]>=a[rr])sub=a[ll++]; else sub=a[rr--]; ma[l][r]=max(ma[l][r],a[ll]+ma[ll+1][rr]-sub); mi[l][r]=min(mi[l][r],a[ll]+mi[ll+1][rr]-sub); ma[l][r]=max(ma[l][r],a[rr]+ma[ll][rr-1]-sub); mi[l][r]=min(mi[l][r],a[rr]+mi[ll][rr-1]-sub); } } } void dfs(int l,int r,int cha){if(r-l+1==hou*2){it=lower_bound(vt[l].begin(),vt[l].end(),-cha);if(it==vt[l].end()||*it==-cha){if(it==vt[l].begin())return ;else it--;}if(cha+*it<0)ans=max(ans,cha+*it);return ;}if(mi[l][r]+cha>=0)return ;if(ma[l][r]+cha<=ans)return ;if(ma[l][r]+cha<0){ans=max(ans,ma[l][r]+cha);return ;}int sub;if(a[l]>=a[r])sub=a[l++]; else sub=a[r--]; dfs(l+1,r,cha+a[l]-sub); dfs(l,r-1,cha+a[r]-sub);}int main(){ int t=clock(); while(~scanf("%d",&n)) { for(int i=0;i<N;i++)vt[i].clear(); for(int i=1;i<=n;i++) scanf("%d",&a[i]); if(n==2) { if(a[1]==a[2])printf("The child will be unhappy...\n"); else printf("%d\n",max(a[1],a[2])-min(a[1],a[2]));continue ; } init(); hou=min(16,n/4),ans=(int)-1e9; for(int i=1;i+hou*2-1<=n;i++) { mp.clear();for(int state=0;state<(1<<hou);state++) { int sum=0,l=i,r=l+2*hou-1; for(int j=0;j<hou;j++) { if(a[l]>=a[r])sum-=a[l++]; else sum-=a[r--]; if(!(state&(1<<j)))sum+=a[l++]; else sum+=a[r--]; } if(mp[sum]==0) {vt[i].push_back(sum);mp[sum]=1; } } sort(vt[i].begin(),vt[i].end()); } dfs(1,n,0); if(ans==(int)-1e9)printf("The child will be unhappy...\n"); else printf("%d\n",-ans); }}
阅读全文
1 0
- HDU 6196 happy happy happy [折半暴搜+剪枝+DP]
- HDU 6196 happy happy happy(暴搜+剪枝+dp)
- hdu 6196 happy happy happy
- HDU 6196 happy happy happy(卡时剪枝)
- happy!
- Happy
- Happy?
- happy
- happy!
- Happy
- happy
- happy
- Happy
- happy
- happy
- Happy
- happy
- happy
- JavaSE,常用类之时间类-区域类-格式类-时区类
- SpringBoot中利用AOP实现拦截器效果
- 无法访问请求的页面,因为该页的相关配置数据无效问题的解决
- caffe+报错︱深度学习参数调优杂记+caffe训练时的问题+dropout/batch Normalization
- P
- HDU 6196 happy happy happy [折半暴搜+剪枝+DP]
- 素数对
- C#梳理【枚举Enum】
- Prepare your Dataset
- 物联网核心之MQTT移植
- JSP 工作原理
- 51nod 1042数位DP 精度
- EditPlus远程连接linux编辑文件
- React Router 页面传值的四种方法