博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[luogu4459][BJOI2018]双人猜数游戏(DP)
阅读量:4352 次
发布时间:2019-06-07

本文共 2720 字,大约阅读时间需要 9 分钟。

从上面的题解中可以找到样例解释,并了解两个人的思维方式。

A和B能从“不知道”到“知道”的唯一情况,就是根据已知条件(也就是已经说的”不知道“次数)排除手上数的所有其它合法拆分方案。

那么,设dp[i][j][k]表示,两个数分别为i,j,当前已经说了k次不知道,这个数是否能确定(也就是某方知道了答案)。

那么有两种转移

dp[i][j][k]|=dp[i][j][k-2]  一轮之前就已经知道了这轮肯定也知道。

对于B: dp[i-s][j+s][k-1]在s取遍所有合法取值时,只有s=0是false,其余全为true。也就是i+j的所有其它合法拆分方案在说了k-2次不知道后,A都应该说知道答案了,唯独这种方案仍不知道,那么B就肯定可以确定这个数了。

对于A: 同理,将i*j拆分即可。

考虑什么情况下满足题设条件,即说了t次”不知道“后双方都知道答案了。

那么就是dp[i][j][t-1]为false而dp[i][j][t]为true。但是这样只能保证已经有一方已知答案,同时还要保证的是另一方当这方说”知道了“之后也知道了答案,而说之前还不知道,这需要另一个类似的暴力拆分解决。

所以我们分别模拟两人的思维,后期每个点大约跑几分钟。

1 #include
2 #include
3 #include
4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 using namespace std; 6 7 const int N=2010; 8 int s,t; 9 bool flag,f[N][N][20];10 char a[10];11 12 bool chk1(int x,int y,int t){13 int num=x*y,len=sqrt(x*y),x1=0,y1=0,cnt=0;14 rep(i,s,len)15 if(num%i==0 && ((!f[i][num/i][t-1])||(!t)))16 x1=i,y1=num/i,cnt++;17 if(cnt==1 && x1==x && y1==y) return 1; else return 0;18 }19 20 bool chk2(int x,int y,int t){21 int num=x+y,len=(x+y)/2,x1=0,y1=0,cnt=0;22 rep(i,s,len)23 if((!f[i][num-i][t-1])||(!t))24 x1=i,y1=num-i,cnt++;25 if(cnt==1 && x1==x && y1==y) return 1; else return 0;26 }27 28 bool chk3(int x,int y,int t){29 int num=x*y,len=sqrt(x*y),x1=0,y1=0,cnt=0;30 rep(i,s,len)31 if(num%i==0 && (f[i][num/i][t]&&(t<2||(!f[i][num/i][t-2]))))32 x1=i,y1=num/i,++cnt;33 if(cnt==1 && x1==x && y1==y) return 1; else return 0;34 }35 36 bool chk4(int x,int y,int t){37 int num=x+y,len=(x+y)/2,x1=0,y1=0,cnt=0;38 rep(i,s,len)39 if(f[i][num-i][t]&&(t<2||(!f[i][num-i][t-2])))40 x1=i,y1=num-i,++cnt;41 if(cnt==1 && x1==x && y1==y) return 1; else return 0; 42 }43 44 int main(){45 freopen("guess.in","r",stdin);46 freopen("guess.out","w",stdout);47 scanf("%d",&s); scanf("%s",a+1); scanf("%d",&t);48 if (a[1]=='A') flag=0; else flag=1;49 rep(i,0,t){50 flag^=1;51 rep(j,s,1000) rep(k,s,1000){52 if(i>=2)f[j][k][i]=f[j][k][i-2];53 f[j][k][i]|=flag?chk1(j,k,i):chk2(j,k,i);54 }55 }56 int sum=2*s,x=0,y=0;57 while (1){58 rep(i,s,sum/2){59 x=i; y=sum-i; flag=f[x][y][t];60 if (!flag) continue;61 rep(j,0,t-1) if(f[x][y][j]){ flag=false; break; }62 if (!flag) continue;63 if(((t&1)&&a[1]=='A')||((!(t&1))&&a[1]=='B')) flag=chk3(x,y,t); else flag=chk4(x,y,t);64 if (!flag) continue;65 printf("%d %d\n",x,y); return 0;66 }67 sum++;68 }69 return 0;70 }

 

转载于:https://www.cnblogs.com/HocRiser/p/10387473.html

你可能感兴趣的文章
hibernate模糊查询-Restrictions.ilike & Expression.like
查看>>
python @property
查看>>
【linux】记录一下遇到的各种问题
查看>>
python学习之day4,函数
查看>>
Java学习之异常处理
查看>>
使用Maven命令安装jar包到仓库中
查看>>
JavaScript 数据类型
查看>>
SQLite数据库
查看>>
[译]Vulkan教程(29)组合的Image采样器
查看>>
combox的DispalyMember和ValueMember属性的测试
查看>>
Start Developing Mac Apps -- Human Interface Design 用户界面设计
查看>>
linux下安装Mongodb
查看>>
Page.RegisterStartupScript和Response.Write的区别。
查看>>
hdu4348区间更新的主席树+标记永久化
查看>>
bzoj3261: 最大异或和 可持久化trie
查看>>
ZOJ 2532 Internship
查看>>
HDU 3452 Bonsai
查看>>
[Erlang12] Mnesia分布式应用
查看>>
图的遍历 | 1013 连通块块数
查看>>
Kinect 开发 —— 进阶指引(上)
查看>>