题意:给你n个两两不同的零一串,Alice在其中选定一个,Bob去猜,每次询问某一位是0 or 1。问你最坏情况下最少要猜几次。
f(22...2)表示当前状态的最小步数,2表示这位没确定,1表示确定为1,0表示确定为0。
首先枚举去问哪一位,从这些方案中取最小者。
这里的MAX(a,b)进行重定义,如果a,b中存在-1,则为真的max(a,b),否则为max(a,b)+1。
f(222)=min(MAX(f(022),f(122)),MAX(f(202),f(212)),MAX(f(220),f(221)));
边界是那些读入的串为0,读入的里面没有的串的值为-1。
队友的代码:
#include <cmath> #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; int T,top,l,n,f[5000000]; char ch; int dfs(int x,int deep) { if(f[x]!=-2) return f[x]; if(deep==l) return f[x]=-1; int xx=x,temp=1; int nowans=100; for(int i=1;i<=l;++i) { if(xx%3==2) { int xxx=x-temp*2; int ans0=dfs(xxx,deep+1); int ans1=dfs(xxx+temp,deep+1); int tempans=max(ans0,ans1); if(ans0!=-1&&ans1!=-1) tempans++; nowans=min(nowans,tempans); } xx/=3; temp*=3; } return f[x]=nowans; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&l); top=1; for(int i=1;i<=l;++i) top=top*3; top-=1; for(int i=0;i<=top;++i) f[i]=-2; for(int i=1;i<=n;++i) { int now=0; for(int i=1;i<=l;++i) { while(ch=getchar(),ch!='0'&&ch!='1'); now=now*3+ch-'0'; } f[now]=0; } printf("%d ",dfs(top,0)); for(int i=0;i<=top;++i) f[i]=-2; } return 0; }