題目連結:http://poj.org/problemstatus?problem_id=2965&start=120&orderby=time&language=-1
這個題目也比較簡單,首先要明確一點,就是每一點翻轉的順序是沒有要求的,也就是一點要麼翻轉,要麼就不翻轉,和順序無關,明白了這一點這個
題目就簡單了,一共就2^16種情況,用二進位位枚舉一下就OK 了,二進位1表示翻轉0表示不翻轉;
其次就是一些技巧上的最佳化
第一:求數字二進位為1的個數,這個用x&x-1這個有多少一就多少次,應該是最快的速度了
第二:把開始char類型的轉換成bool型的,方便處理
第三:用位元運算計算那一位是否為1,這樣速度快點
第四:用G++交,可能GNU的編譯器對位元運算的最佳化要好一些
#include <iostream>#include <string.h>#include <stdio.h>using namespace std;#define maxn 1<<16char rec[4][4];bool map[4][4];bool temp[4][4];int init(){ int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) if(rec[i][j]=='+') map[i][j]=true; else map[i][j]=false; return 0;}bool is_ok(){ bool flag=false; int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) { flag=temp[i][j]||flag; } return flag==false;}int num_of_two(int a){ int num=0; while(a) { a=a&(a-1); num++; } return num;}int change(int i,int j){ int a; for(a=0;a<4;a++) temp[i][a]=!temp[i][a],temp[a][j]=!temp[a][j]; temp[i][j]=!temp[i][j];//three return 0;}bool find_ans(int k){ int i; for(i=0;i<16;i++) { if(k&(1<<i)) change(i%4,i/4); } return is_ok();}int out_put(int k){ for(int i=0;i<16;i++) { if(k&(1<<i)) printf("%d %d\n",i%4+1,i/4+1); } return 0;}int main(){ int i,j,k; int ans=0,num_two,n; while(scanf("%s",rec[0])!=EOF) { num_two=10000; ans=0; scanf("%s%s%s",rec[1],rec[2],rec[3]); init(); for(i=0;i<maxn;i++) { n=num_of_two(i); if(n>=num_two) continue; memcpy(temp,map,sizeof(map)); if(find_ans(i)) ans=i,num_two=n; } printf("%d\n",num_two); out_put(ans); } return 0;}