【状压dp】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem E. Guessing Game

题意:给你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\n",dfs(top,0));
for(int i=0;i<=top;++i)
f[i]=-2;
}
return 0;
}
上一篇:JDK1.8源码(二)——java.util.LinkedList


下一篇:Go语言(golang)开源项目大全