#include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; /** Problem : UVA11205 - The broken pedometer Begin Time: 28th/Mar/2012 11:30 a.m. Finish Time: 29th/Mar/2012 2:14 a.m. Last Time : About 6 hours. State:9924407 11205 The broken pedometer Accepted C++ 2.684 2012-03-28 18:11:32 Knowledge : BFS,剪枝都没有,还有子集生成,也算有个小小的状态压缩? Exp.: WA * 4 :这四个Wrong Answer奉献给了误把BFS写成DFS,不应该 WA * 4 :我他妈对于后四个WA无力吐槽了啊我操。边界,边界! tmp.depth + 1 <= col写成了 tmp.depth + 1 < col结果就少了一组组合啊!过脑子啊白痴!写程序时。 操操操操操。 Thought: 每行换成10110101这样的整数(因为最多才2^15,不用位运算了,否则怪麻烦的) 开一个数组isSel[],如果ith列被选了那么isSel[i] = true; 然后根据isSel判断目前选的列数,以及应该从那几列中抽取子集。 其实位运算能快一些。 Summerize: 发现搜索出错的时候 1.仔细想一下搜索的过程,状态转移的方式,是否有状态结点未展开 2.想一下边界,是否有问题 最重要的,写之前看清楚了,一般有最短,最少,最小字样的统统为BFS. 搜索的如果是个树,则不需要回溯,如果是个图,则需要回溯。 */ const int MAXN = 200; const int MAXP = 50; int puzzle[MAXN][MAXP]; int subset[MAXN]; bool isSel[MAXN]; int minN; bool isFound; struct node { int depth; bool isSel[MAXN]; }; node tmp; queue<node> que; int comp(const void *a, const void *b) { return (*(int*)a - *(int*)b); } bool check(int row,int col) { int cnt = 0; memset(subset,0,sizeof(subset)); for(int i = 0 ; i < col ; i++) { if(isSel[i] == true) cnt++; } for(int j = 0 ; j < row ; j++) { for(int i = 0 ; i < col ; i++) { if(isSel[i] == true ) { subset[j] = subset[j] * 10 + puzzle[j][i]; } } } qsort(subset,row,sizeof(int),comp); int i = 0; int j = i+1; while( j < row ) { if(subset[i] == subset[j]) { return false; } i++,j++; } if( minN > cnt) { minN = cnt; } return true; } int Solve(int row,int col,int now) { node tmp,tmp1,k; while(!que.empty()) { tmp=que.front(); que.pop(); memcpy(isSel,tmp.isSel,sizeof(isSel)); tmp1 = tmp; check(row,col); if(tmp.depth + 1 <= col) { tmp1.depth = tmp.depth + 1; tmp1.isSel[tmp1.depth - 1] = false; que.push(tmp1); tmp1.isSel[tmp1.depth - 1] = true; que.push(tmp1); } } return minN; } int main() { #ifndef ONLINE_JUDGE freopen("b:\\acm\\UVA\\UVA11205\\input.txt","r",stdin); freopen("b:\\acm\\uva\\uva11205\\output.txt","w",stdout); #endif int T,P,N,k; // while( scanf("%d",&T) != EOF ) scanf("%d",&T); { for(int t = 1 ; t <= T ; t++) { scanf("%d%d",&P,&N); memset(puzzle,0,sizeof(puzzle)); memset(subset,0,sizeof(subset)); memset(isSel,0,sizeof(isSel)); for(int i = 0 ; i < N ; i++) { for(int j = 0 ; j < P ; j++) { scanf("%d",&puzzle[i][j]); } } minN = 200; tmp.depth = 1; tmp.isSel[0] = true; que.push(tmp); tmp.depth = 1; tmp.isSel[0] = false; que.push(tmp); k = Solve(N,P,0); printf("%d\n",k); while(!que.empty()) { que.pop(); } } } return 0; }