[BJOI2018]双人猜数游戏

题解:

彻彻底底的思维题???还是挺难的。。

首先连样例解释都没给。。没看题解搞了很久

大概就是

一个人要根据另一个人的决策来猜数

可以去看洛谷那篇题解的解释

然后我们用$f[A/B][i][j][k]$

表示第i次操作时,$A/B$能否判断出(j,k)

然后这个挺好dp

另外如果$f[i-1][xx]$可以的话$f[i][xx]$也一定可以

后面要注意两种情况

1.扩展出当前情况的时候

一定要满足其他的已经扩展出,但是当前的没有扩展出(因为这个查了很久)

2.最后一次扩展的时候,如果只能多扩展出这一个,那也是可行的

这个不知道第一个样例就过不了

另外答案是两个之和最小。。。

25组也就1s左右吧

代码:

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
int n,m;
const int M=300;
bool f[20][M][M];
char cc[10];
IL bool pd1(bool (*f) [M],int k,int now)
{
  rep(i,m,k)
  {
    int j=k-i;
    if (i>j) break;
    if (now!=i&&!f[i][k-i]) return(0);
  }
  if (!f[now][k-now]) return(1);
  else return(0);
}
IL bool pd2(bool (*f) [M],int k,int now)
{
  rep(i,m,k)
  {
    int t=k/i;
    if (i>t) break;
    if (t*i==k)
      if (now!=i&&!f[i][t]) return(0);
  }
  if (!f[now][k/now]) return(1);
  else return(0);
}
IL bool pd3(bool (*f1) [M],bool (*f2) [M],int k,int now)
{
  rep(i,m,k)
  {
    int j=k-i;
    if (i>j) break;
    if (now!=i&&f1[i][k-i]!=f2[i][k-i]) return(0);
  }
  if (f2[now][k-now]&&!f1[now][k-now]) return(1);
  else return(0);
}
IL bool pd4(bool (*f1) [M],bool (*f2) [M],int k,int now)
{
  rep(i,m,k)
  {
    int t=k/i;
    if (i>t) break;
    if (t*i==k)
      if (now!=i&&f1[i][t]!=f2[i][t]) return(0);
  }
  int t=k/now;
  if (f2[now][t]&&!f1[now][t]) return(1);
  else return(0);
}
int main()
{
  rep(tt,1,25)
  {
    me(f);
  char c1[20]="guess";
  int now=4;
  if (tt>=10) c1[++now]=tt/10+48,c1[++now]=tt%10+48;
  else c1[++now]=tt%10+48;
  c1[++now]='.'; c1[++now]='i'; c1[++now]='n';
  
  char c2[20]="guess";
  now=4;
  if (tt>=10) c2[++now]=tt/10+48,c2[++now]=tt%10+48;
  else c2[++now]=tt%10+48;
  c2[++now]='.'; c2[++now]='o'; c2[++now]='u'; c2[++now]='t';
  freopen(c1,"r",stdin);
  freopen(c2,"w",stdout);
  ios::sync_with_stdio(false);
  cin>>n>>cc>>m;
  swap(n,m);
  int tf;
  if (cc[0]=='B') tf=0; else tf=1;
  if (!tf)
  {
    rep(i,1,M)
      rep(j,1,M)
        if (i<=j&&i>=m&&j>=m)
        if (pd1(f[2],i+j,i)) f[1][i][j]=1;
    rep(i,1,M)
      rep(j,1,M)
        if (i<=j&&i>=m&&j>=m)
        if (pd2(f[2],i*j,i)) f[0][i][j]=1;
  } else
  {
     rep(i,1,M)
      rep(j,1,M)
        if (i<=j&&i>=m&&j>=m)
        if (pd2(f[2],i*j,i)) f[1][i][j]=1;
    rep(i,1,M)
      rep(j,1,M)
        if (i<=j&&i>=m&&j>=m)
        if (pd1(f[2],i+j,i)) f[0][i][j]=1;
  }
  rep(k,2,n+1)
  {
    rep(i,1,M)
      rep(j,1,M)
        f[k][i][j]=f[k-2][i][j];
    if ((k+tf)%2==1)
    {
      rep(i,1,M)
        rep(j,1,M)
          if (i<=j&&i>=m&&j>=m)
          if (pd1(f[k-1],i+j,i)) f[k][i][j]=1;
    }
    else
      rep(i,1,M)
        rep(j,1,M)
          if (i<=j&&i>=m&&j>=m)
          if (pd2(f[k-1],i*j,i)) f[k][i][j]=1;
  }
  rep(i,1,M)
    rep(j,1,M)
      if (i>=m&&j>=m)
      if ((n+tf)%2==1)
      {
        if (pd3(f[n-1],f[n+1],i+j,i)) f[n][i][j]=1;
      } else
      {
        if (pd4(f[n-1],f[n+1],i*j,i)) f[n][i][j]=1;
      }
  n++;
  int mina=1e9,minb=1e9;
  rep(i,1,M)
    rep(j,1,M)
      if (f[n][i][j]&&f[n-1][i][j]&&!f[n-2][i][j]&&!f[n-3][i][j]&&((i+j<mina+minb)||((i+j)==mina+minb&&(i<mina))))
      {
        mina=i,minb=j;
      }
    cout<<mina<<" "<<minb<<endl;
    int a;
  }
  return 0;
}

 

posted @ 2018-11-25 16:30  尹吴潇  阅读(632)  评论(0编辑  收藏  举报