题意:有4×4个开关,每改变一个开关的状态,会同时改变同一行和同一列开关的状态,给出初始状态,求最少需要多少步能把所有开关都变成开,并输出方案。
解法:枚举+剪枝。直接暴力枚举竟然T了……觉得不太科学……2^16*16的复杂度而已……只好加了一个剪枝,记录当前已经枚举过的最佳答案,后来就只枚举到最佳答案,如果超过了最佳答案的步数说明肯定不是最佳方案。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
using namespace std;
int main()
{
ios :: sync_with_stdio(false);
char maze[4][5];
while(cin >> maze[0])
{
for(int i = 1; i < 4; i++)
cin >> maze[i];
int maxn = 1 << 16;
int ans = 1000000, pos = 0;
for(int i = 0; i < maxn; i++)
{
int res = 0;
int cnt[4][4] = {0};
int flag = 1;
for(int j = 0; j < 16; j++)
{
if(i & (1 << j))
{
res++;
if(res > ans)//剪枝
{
flag = 0;
break;
}
for(int k = 0; k < 4; k++)
{
cnt[j / 4][k]++;
cnt[k][j % 4]++;
}
cnt[j / 4][j % 4]--;
}
}
for(int j = 0; j < 4 && flag; j++)
for(int k = 0; k < 4 && flag; k++)
{
int tmp = maze[j][k] == ‘+‘ ? 1 : 0;
tmp += cnt[j][k];
if(tmp & 1) flag = 0;
}
if(flag && (res < ans))
{
ans = res;
pos = i;
}
}
if(ans != 1000000)
cout << ans << endl;
else
cout << "0" << endl;
for(int i = 0; i < 16; i++)
{
if(pos & (1 << i))
{
cout << i / 4 + 1 << ‘ ‘ << i % 4 + 1 << endl;
}
}
}
return 0;
}
POJ 2965 The Pilots Brothers' refrigerator
原文:http://www.cnblogs.com/Apro/p/4859156.html