zoukankan      html  css  js  c++  java
  • [luogu4459][BJOI2018]双人猜数游戏(DP)

    https://zhaotiensn.blog.luogu.org/solution-p4459

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

    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<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     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
    ",x,y); return 0;
    66         }
    67         sum++;
    68     }
    69     return 0;
    70 }
  • 相关阅读:
    等价类测试实践
    软件测试
    软件测试第八周——业内人员的感触与建议
    软件测试第七周——互联网测试
    软件测试第六周——白盒测试
    Hessian matrix
    软件测试第5周——VisualStudio 2013 编码的UI测试
    软件测试第四周——String 转 int
    软件测试第三周——测试框架
    软件测试第二周学习
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10387473.html
Copyright © 2011-2022 走看看