神奇的bfs做法:
对于每个串si,枚举所有的串x
(1<=i<=n)
第一层SIM(si,x)=m,即本身
第二层SIM(si,x)=m-1,
第三层SIM(si,x)=m-2.....
假设SIM(si,x)=v,并且x没有被访问过,那么x必然是可行且更优的,因为使得SIM(si,x)=v+1,v+2.....m的x都被枚举过了,
以x去和n个串计算SIM,得到的值必定<=v
用dp[sta]记忆化搜索,如果sta作为最佳答案T,那么dp[sta]就是sta对n个串分别求SIM值中的最大值
#include<bits/stdc++.h>
#define RD1(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d %d",&x,&y)
#define RD3(x,y,z) scanf("%d %d %d",&x,&y,&z)
#define RDL1(x) scanf("%lld",&x)
#define RDL2(x,y) scanf("%lld %lld",&x,&y)
#define RDL3(x,y,z) scanf("%lld %lld %lld",&x,&y,&z)
#define CLR(x) memset(x,0,sizeof(x))
#define NEG(x) memset(x,0xff,sizeof(x))
#define maxm (1111+10)
#define maxn (1000000+10)
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mod (100000007)
#define pi acos(-1)
#define eps 1e-14
#define acc ios::sync_with_stdio(false);cin.tie(0)
#define inf 0x3f3f3f3f
#define INF(x) memset(x,inf,sizeof(x))
#define CLRQ(Q) while(!(Q).empty())(Q).pop()
#define see(x) (cerr<<(#x)<<'='<<(x)<<' ')
#define NL printf("\n")
#define fi freopen("C:\\Users\\Administrator\\Desktop\\in","r",stdin)
#define fo freopen("C:\\Users\\Administrator\\Desktop\\out","w",stdout)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int n,m,a[maxn];char buf[30];
queue<int>Q;
int dp[1<<21];
int main()
{
	INF(dp);
	acc;cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>buf;for(int j=m-1;j>=0;j--)
		{
			a[i]<<=1;
			a[i]|=buf[j]-'0';
		}
		Q.push(a[i]);dp[a[i]]=m;
	}
	int ans=m;
	while(!Q.empty())
	{
		int u=Q.front();Q.pop();
		ans=min(ans,dp[u]);
		for(int i=0;i<m;i++)
		{
			int v=u^1<<i;
			if(dp[v]==inf)
			{
				Q.push(v);dp[v]=dp[u]-1;
			}
		}
	}
	cout<<ans;
	return 0;
}