我终于可以说这是我自己独立完成的题目了,没看题解,没看注释,虽然用的时间成了写,总归有成就感的,昨天晚上就写了个大概,有点bug,由于太晚了,而且有点困了,就去睡了,当时真是自己认真想了的,,很深入的想了,用的书上刚学会的位向量自己生成来判断的。以后都要努力自己想,自己解决,专注。。。深入。。。。
思路:
就是先算出最少用m个灯才能表示n个数字,然后找第一个数字(由许多灯组成的0,1序列)的个数为m的子
集,把这n个子集作为n个数字的下标,判断一下有没有玩去一样的,如果有的话证明这两个数字不能通过m个灯来判
断,然后就把m加1,找第一个数字个数为m+1的子集,和m的时候一样进行判断
代码:
#include<stdio.h> #include<string.h> #include<stdlib.h> int B[20]; int sum; int map[105][20]; int ans; int res[20]; int flag,n; void find(int m,int *B,int cur) { if(flag) return ; if(cur == m) { if(ans!=sum) return ; int k = 0; memset(res,0,sizeof(res)); for(int i=0; i<cur; i++) { if(B[i]) { res[k++] = i; } } //puts(""); //puts("***********************"); //for(int p=0; p<k; p++) // printf("%d ",res[p]); //puts(""); for(int i=0; i<n; i++) { for(int j=i+1; j<n; j++) { int nodeng = 0; for(int p=0; p<k; p++) { //printf("%d ",res[p]); if(map[i][res[p]]!=map[j][res[p]]) { //printf("ii = %d jj = %d\n",i,j); //printf("k = %d\n",k); //printf("p = %d\n",res[p]); nodeng = 1; break; } } //puts("**************"); if(nodeng==0) { // printf("i = %d j = %d\n",i,j); // printf("map[0][3] = %d map[8][3] = %d\n",map[0][3],map[8][3]); //system("pause") ; return ; } } } flag = 1; //puts("***********************"); return ; } B[cur] = 1; ans++; find(m,B,cur+1); B[cur] = 0; ans--; find(m,B,cur+1); } int main() { int T,m,i,j; scanf("%d",&T); while(T--) { memset(B,0,sizeof(B)); memset(map,0,sizeof(map)); scanf("%d%d",&m,&n); //m表示灯的个数,n表示数字的个数 for(i=0; i<n; i++) for(j=0; j<m; j++) scanf("%d",&map[i][j]); //printf("**map[0][3] = %d map[8][3] = %d\n",map[0][3],map[8][3]); if(n==1) { printf("%d\n",0); continue; } if(m==0||n==0) { printf("%d\n",0); continue; } int x = 1; ans = 0; for(i=1; i<=m; i++) { x*=2; if(x >= n) { x = i; break; } } //printf("x = %d\n",x); sum = x; flag = 0; for(sum=x; sum<=m; sum++) { find(m,B,0); if(flag) { printf("%d\n",sum); break; } } } return 0; }