题意有点绕 等于说是求最优策略下 即排除方案最优的情况下 需要排除最多次的集合的排除次数 详见代码注释
#include<bits/stdc++.h>
const int maxn=13;
char objects[300][200];
int d[1<<maxn][1<<maxn],cnt[1<<maxn][1<<maxn],vis[1<<maxn][1<<maxn];
//d[s][a] s a状态下的最小次数 cnt[s][a]满足这个集合的字符串数 vis[s][a]记忆化
using namespace std;
int n,m;
int dp(int s, int a){
if(cnt[s][a]<=1)return 0;
if(cnt[s][a]==2)return 1;
int &ans=d[s][a];
if(vis[s][a])return ans;
vis[s][a]=1;
ans=m;
for(int k=0;k<m;k++){
if(!(s&(1<<k))){
int s2=s|(1<<k),a2=a|(1<<k);
if(cnt[s2][a2]>=1&&cnt[s2][a]>=1){
int need=max(dp(s2,a2),dp(s2,a))+1;
ans=min(ans,need);
}
}
}
return ans;
}
void init() {
for(int s = 0; s < (1<<m); s++) {
for(int a = s; a; a = (a-1)&s)//a是s的子集 cnt[s][a]记录满足这个状态的物品有多少个
cnt[s][a] = 0;
cnt[s][0] = 0;
}
for(int i = 0; i < n; i++) {
int features = 0;
for(int f = 0; f < m; f++)
if(objects[i][f] == '1') features |= (1<<f);
for(int s = 0; s < (1<<m); s++)
cnt[s][s & features]++; //计算满足s a的串个数
}
}
int main(){
while(scanf("%d%d",&m,&n)==2&&n){
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)scanf("%s",objects[i]);
init();
printf("%d\n",dp(0,0));
}
return 0;
}