emmm, 第一次做按位的搜索,想了一会还是借鉴了大佬的题解~
https://blog.csdn.net/nealgavin/article/details/10648605
记录一下:这里的DP(s, ans) 中 s 为1的位指的是已经判断过的位,不用再判断,ans指的是当前已经判断过得到的不完全的数字,是从s变过来的。
其中结束的标志
{
if((s & b[i]) == ans)
num++;
}
if(num <= 1)
{
dp[s][ans] = 0;
return 0;
}
指的是这个当前的ans已经可以准确定位了,不用在往下做了。
如果num > 1
那么至少还有两个不能区分,还要继续,所以返回的肯定不是0,不需要担心某个数不是输入中的一个的情况
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
int mx = 2050;
int dp[2050][2050];
int b[130];
int n, m;
char a[15];
int DP(int s, int ans)
{
if(dp[s][ans] != -1)
return dp[s][ans];
int num = 0;
int i, j, k;
for(i = 0; i < m; i++)
{
if((s & b[i]) == ans)
num++;
}
if(num <= 1)
{
dp[s][ans] = 0;
return 0;
}
int to, ret = mx;
for(i = 0; i < n; i++)
{
if(s & (1 << i))
continue;
to = s | (1 << i);
int toans = ans | (1 << i);
dp[to][ans] = DP(to, ans);
dp[to][toans] = DP(to, toans);
ret = min(ret, max(dp[to][toans], dp[to][ans]) + 1);
}
dp[s][ans] = ret;
return ret;
}
int main()
{
int i, j, k;
while(scanf("%d%d", &n, &m))
{
if(!m && !n)
break;
for(i = 0; i < m; i++)
{
k = 0;
scanf("%s", a);
for(j = 0; j < n; j++)
{
k = k * 2 + a[j] - '0';
}
b[i] = k;
}
if(m == 1)
{
cout << 0 << endl;
continue;
}
memset(dp, -1, sizeof(dp));
cout << DP(0, 0) << endl;
}
return 0;
}