您的位置:首页 > 其它

暴力枚举-POJ2965 The Pilots Brothers' refrigerator

2014-04-12 08:48 309 查看
题目大意:(直接说关键的了)一组4*4的开关,每次可以选择一个开关操作,操作时把它所在行及所在列的开关全部取反(包括它自己),问最少经过几次操作可以把开关全都打开(‘+’:关  ‘-’ :开),并给出操作的过程

 这题和POJ1753是一样的,不过时间卡的特别紧,1753的代码改下交T掉了,没办法,逼着自己写位运算吧····
为了纪念我墨迹了好久,给代码加了注释


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include <algorithm>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define ll long long
#define eps 1e-8
#define ms(x,y) (memset(x,y,sizeof(x)))
#define fr(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
const int maxn=65537;
int key;
int dir[16]={63624,62532,61986,61713,36744,20292,12066,7953,35064,17652,8946,4593,34959,17487,8751,4383};//翻转
int loc[16];//第i位是否为1
void init()
{
key=0;
fr(i,0,15)
{
char ch;
cin>>ch;
if(ch=='+')
key+=1;
key<<=1;
}
key>>=1;
loc[0]=1;
fr(i,1,15)
loc[i]=loc[i-1]<<1;
}
int num(int n)//返回操作需要的步骤数
{
int s=0;
fr(i,0,15)
{
if(n&loc[i])//判断当前位是否为1
s++;
}
return s;
}
void doit()
{
int ans=16,path=0;
fr(i,1,65535)//枚举路径
{
int k=key;
fr(j,0,15)
{
if(i&loc[j])
k^=dir[j];//翻转
}
if(!k)
{
int s=num(i);
if(ans>s)
{ans=s;path=i;}//如果答案比当前大 替换 并且记录路径
}
}
if(ans!=16)//特判16
{
cout<<ans<<endl;
int a[16];
ms(a,0);
fr(i,0,15)
{
if(path%2)a[i]=1;
path/=2;
}//把路径翻译出来
fr(i,0,15)
{
if(a[i])cout<<i/4+1<<' '<<i%4+1<<endl;
}
}
else
{
cout<<16<<endl;
fr(i,0,15)cout<<i/4+1<<' '<<i%4+1<<endl;
}
}
int main()
{
init();
doit();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  枚举