【狀壓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;
}
相關文章
相關標籤/搜索