http://poj.org/problem?id=1753
题意:一个类似点灯游戏的东西,求灯全亮或全灭的最小步数。
一般想到是BFS,但是武大给的是枚举,果然是枚举啊啊啊啊!!因为点某几个灯之后的结果是相同的,与点这几个灯的顺序无关!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
#define N 100005
bool c[5][5],a[5][5];
int x,y,b[20]={0};
void init()
{
int i,j;
for (i=1;i<=4;i++)
for (j=1;j<=4;j++)
a[i][j]=c[i][j];
}
void bplus()//把b作为一个从0到2^16-1的数字的二进制表达的串
{
b[16]++;
int i=16;
while (b[i]==2)
{
b[i]=0;
b[i-1]++;
i--;
}
}
void getxy(int m)
{
x=(m-1)/4+1;
y=m%4;
if (y==0) y=4;
}
void fan(int x,int y)
{
a[x][y]=!a[x][y];
}
bool check()
{
int sum=0,i,j;
for (i=1;i<=4;i++)
for (j=1;j<=4;j++)
if (a[i][j]==true) sum++;
if (sum==0 || sum==16) return true;
else return false;
}
int count()
{
int i,sum=0;
for (i=1;i<=16;i++) sum+=b[i];
return sum;
}
int main()
{
//freopen("a","r",stdin);
int j,i,min=100;
char ch;
for (i=1;i<=4;i++)
{
for (j=1;j<=4;j++)
{
cin>>ch;
if (ch=='b') c[i][j]=false;
else c[i][j]=true;
}
}
b[16]=-1;
for (i=0;i<=65535;i++)//枚举该翻哪些点
{
init();
bplus();
for (j=1;j<=16;j++)
if (b[j]==1)
{
getxy(j);
fan(x,y);
if (x>1) fan(x-1,y);
if (x<4) fan(x+1,y);
if (y>1) fan(x,y-1);
if (y<4) fan(x,y+1);
}
if (check())
{
if (count()<min) min=count();
}
}
if (min<100) cout<<min;
else cout<<"Impossible";
return 0;
}