用增量构造法来生成子集。如果可以从个数由少到多生成子集,而不是按照字典序的话,那么可以更快得到答案。鉴于这样的考虑,当得到最小的子集个数,那么当前所需的个数大于最小的个数,就不用考虑其是否满足题意。这样做更快。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn=110;
int B[maxn][20],min,A[20],n,p;
int is_ok(int cur)
{
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
int ok=1;
for(int k=0;k<cur;k++)
if(B[i][A[k]]!=B[j][A[k]]) {ok=0;break;}
if(ok) return 0;
}
return 1;
}
void try_subset(int cur)
{
if(min>cur &&is_ok(cur)) min=cur;
int s=cur?A[cur-1]+1:0;
for(int i=s;i<p;i++)
{
A[cur]=i;
try_subset(cur+1);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("11205.txt","r",stdin);
#endif
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&p,&n);
int i,j;
for(i=0;i<n;i++)
for(j=0;j<p;j++)
scanf("%d",&B[i][j]);
/*for(i=0;i<n;i++)
{
for(j=0;j<p;j++)
printf("%d ",B[i][j]);
printf("\n");
}*/
min=20;
try_subset(0);
printf("%d\n",min);
}
return 0;
}