poj 1753

来源:互联网 发布:淘宝apple store 编辑:程序博客网 时间:2024/05/20 08:42

       这道题就是所谓的“关灯问题”。在《算法设计与分析基础》课后习题中见过。 乍一看,最容易想到用16个(0、1)变量列一个线性方程组(16维的),然后高斯消去求解。但是感觉高斯消去法写起来太累人。又想别的方法。出现在脑袋里的是暴力法,由于只有2^16个解,所以暴力是可以解决的。然后又想到用一个int型数据的低16位表示棋盘,然后对棋盘进行位运算操作效率较高。

discuss里有很多所谓的官方测试数据,可以先测试一下再提交。

poj1753代码:

#include<iostream>#include<fstream>#include<time.h>using namespace std;inline void set0(int &data,int index){data&=(~(1<<index));}inline void set1(int &data,int index){data|=(1<<index);}inline int getbit(const int &data,int index){return data&(1<<index);}int data;void put(char *ch,int index){  for(int i=0;i<4;i++,index++)  { if(ch[i]=='b') {  set0(data,index); } else if(ch[i]=='w') {  set1(data,index);     } } }int rem[16]={};//0表示b 1表示wvoid solve(){const int final0=0; const int final1=65535;int change;int temp=data;int min=100;for(change=0;change<65536;change++){//data 根据i的每一位做相应变化for(int i=0;i<16;i++){if(getbit(change,i)!=0){data=data^rem[i];}}if(data==final0||data==final1){ int count=0;//统计i中 “1” 的个数, for(int i=0;i<16;i++)     {    if(getbit(change,i)!=0)count++;     } if(count<min) min=count;}data=temp;}if(min==100)cout<<"Impossible"<<endl;else{cout<<min<<endl;}}int main( ){memset(rem,0,sizeof(int)*16);for(int i=0;i<16;i++){set1(rem[i],i);if(i-4>=0)set1(rem[i],i-4);if(i%4!=0)set1(rem[i],i-1);if(i%4!=3)set1(rem[i],i+1);if(i+4<16)set1(rem[i],i+4);}ifstream cin("input.txt");char ch[5];while(cin>>ch){int index=0;data=0;put(ch,index);index+=4;for(int k=0;k<3;k++){cin>>ch;put(ch,index);index+=4;}solve();} return 0;}