【状压dp】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 201

题意:给你n个两两不一样的零一串,Alice在其中选定一个,Bob去猜,每次询问某一位是0 or 1。问你最坏状况下最少要猜几回。ios

f(22...2)表示当前状态的最小步数,2表示这位没肯定,1表示肯定为1,0表示肯定为0。spa

首先枚举去问哪一位,从这些方案中取最小者。blog

这里的MAX(a,b)进行重定义,若是a,b中存在-1,则为真的max(a,b),不然为max(a,b)+1。get

f(222)=min(MAX(f(022),f(122)),MAX(f(202),f(212)),MAX(f(220),f(221)));string

边界是那些读入的串为0,读入的里面没有的串的值为-1。it

队友的代码:io

#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;
}
相关文章
相关标签/搜索