POJ-3809-Twenty Questions

来源:互联网 发布:知我者二三子典故 编辑:程序博客网 时间:2024/04/27 23:03
这个题好麻烦,按照白书的提醒加上自己想了一下总算做出来了。主要是位运算记录状态,转移方程式为dp[i][j]=min(dp[i][j],max(dp[i|(1<<k)][j|(1<<k)],dp[i|(1<<k)][j];
代码:
#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int inf=1<<29;const int maxn=130;const int maxm=1<<11;int n,m,up,a[maxn],cnt[maxm][maxm],dp[maxm][maxm];void Init(){    memset(cnt,0,sizeof(cnt));    for(int i=0;i<up;i++)         for(int j=0;j<n;j++)             cnt[i][i&a[j]]++;    for(int i=0;i<up;i++)        for(int j=0;j<up;j++)            dp[i][j]=inf;}void solve(){    up=1<<m;    Init();    for(int i=0;i<up;i++)        for(int j=0;j<up;j++)            if(cnt[i][j]==1)                dp[i][j]=0;    for(int i=up-1;i>=0;i--)        for(int j=up-1;j>=0;j--)            if((i&j)==j)                for(int k=0;k<m;k++)                    if(!(i&(1<<k)))                        dp[i][j]=min(dp[i][j],max(dp[i|(1<<k)][j|(1<<k)],dp[i|(1<<k)][j])+1);    printf("%d\n",dp[0][0]);}int main(){    while(scanf("%d%d",&m,&n)&&(n+m))    {        memset(a,0,sizeof(a));        for(int i=0;i<n;i++)        {            char str[12];            scanf("%s",str);            for(int j=0;j<m;j++)                if(str[m-1-j]=='1')                    a[i]|=1<<j;        }        solve();    }    return 0;}


0 0