POJ2965
The Pilots Brothers’ refrigerator
Time Limit: 1000MS | Memory Limit: 65536K | |||
---|---|---|---|---|
Total Submissions: 33516 | Accepted: 12994 | Special Judge |
Description
The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to open a refrigerator.There are 16 handles on the refrigerator door. Every handle can be in one of two states: open or closed. The refrigerator is open only when all handles are open. The handles are represented as a matrix 4х4. You can change the state of a handle in any location [i, j] (1 ≤ i, j ≤ 4). However, this also changes states of all handles in row i and all handles in column j.The task is to determine the minimum number of handle switching necessary to open the refrigerator.
Input
The input contains four lines. Each of the four lines contains four characters describing the initial state of appropriate handles. A symbol “+” means that the handle is in closed state, whereas the symbol “−” means “open”. At least one of the handles is initially closed.
Output
The first line of the input contains N – the minimum number of switching. The rest N lines describe switching sequence. Each of the lines contains a row number and a column number of the matrix separated by one or more spaces. If there are several solutions, you may give any one of them.
Sample Input
-+--
----
----
-+--
Sample Output
6
1 1
1 3
1 4
4 1
4 3
4 4
Source
Northeastern Europe 2004, Western Subregion
- 暴力枚举
- 一个深搜结局了…
- 16个位置, 改变或者不改变向下搜索
- 要骚解法?—>此处是骚解法
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int maxn = 25;
const int INF = 0x3f3f3f3f;
int g[5][5];
int tmp_x[maxn];
int tmp_y[maxn];
int ans_pathx[maxn];
int ans_pathy[maxn];
int ans = INF;
void traverse(int pos){
int tx = pos / 4, ty = pos % 4;
g[tx][ty] = !g[tx][ty];
for (int i = 0; i < 4; i++){
g[i][ty] = !g[i][ty];
g[tx][i] = !g[tx][i];
}
}
bool ok(){
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++)
if (g[i][j] == 0) {
return false;
}
}
return true;
}
//遍历到了第pos个, 翻转了traverse_num个
void dfs(int pos, int traverse_num){
if (ok()){
if (ans > traverse_num){
ans = traverse_num;
for (int i = 0; i < ans; i++){
ans_pathx[i] = tmp_x[i], ans_pathy[i] = tmp_y[i];
}
}
return;
}
if (pos >= 16) {
return;
}
//第pos个不翻转
dfs(pos + 1, traverse_num);
//翻转存入g中
traverse(pos);
tmp_x[traverse_num] = pos / 4 + 1;
tmp_y[traverse_num] = pos % 4 + 1;
dfs(pos + 1, traverse_num + 1);
traverse(pos);
}
int main(){
char c;
memset(g, 0, sizeof(g));
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++) {
cin >> c;
if (c == '-') {
g[i][j] = 1;
}
else {
g[i][j] = 0;
}
}
}
dfs(0, 0);
cout << ans << "\n";
for (int i = 0; i < ans; i++){
printf("%d %d\n", ans_pathx[i], ans_pathy[i]);
}
return 0;
}
-
原本想改改POJ1765的代码的, 改了半天, 还T了. 这个代码写的复杂了, 贴在这留个纪念.
#pragma warning(disable:4996) #include <cstring> #include<iostream> #include<cstdio> #include<algorithm> #include<queue> using namespace std; const int maxn = 10; const int MAXN = 100000; //每个地方的字符有改和不改的两种情况 //故一共2**16种状态 //每个地方的字符改一次和两次和若干次取得的效果相同 //采用状态压缩, 一个状态压缩为一个int char g[maxn][maxn]; int path[17]; int ans[17]; //当前的值cur, 需要翻转的个数times, 当前光标所在的位置pos, 当前已翻转的个数cur_times bool traverse(int cur, int times, int pos, int cur_times) { if (cur_times == times) { if (cur == 0) { for (int i = 0; i < 16; i++) { ans[i] = path[15 - i]; } return true; } return false; } if (pos >= 16) { return false; } int curr; for (int i = pos; i < 16; i++) { curr = cur ^ (1 << i); path[i] = 1; int tmp[5][5]; int cnt = 0; for (int i = 3; i >= 0; i--) { for (int j = 3; j >= 0; j--) { tmp[i][j] = !!(curr & (1 << cnt)); cnt++; } } int x, y; x = i / 4; y = i % 4; x = 3 - x; y = 3 - y; //那一列的翻转 for (int i = 0; i < 4; i++) { tmp[i][y] = tmp[i][y] ^ 1; } //那一行的翻转 for (int i = 0; i < 4; i++) { tmp[x][i] = tmp[x][i] ^ 1; } curr = tmp[0][0] == 1 ? 1 : 0; /* for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { cout << tmp[i][j] << " "; } cout << endl; }*/ //将数组中的值组合成一个int for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (i + j == 0) { continue; } curr <<= 1; curr += tmp[i][j]; } } if (traverse(curr, times, i + 1, cur_times + 1)) { return true; } path[i] = 0; } return false; } //关闭的'+'用1 int solve() { int cur = g[0][0] == '+' ? 1 : 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (i + j == 0) { continue; } //左移一位 cur <<= 1; if (g[i][j] == '+') { cur += 1; } } } if (cur == 0) { return 0; } // int last = cur; //改变的开关的个数, last为当前开关的状态 for (int i = 1; i <= 16; i++) { if (traverse(last, i, 0, 0)) { return i; } } return -1; } int main() { char c; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { cin >> c; g[i][j] = c; } } int res = solve(); cout << res << "\n"; for (int i = 0; i < 16; i++) { if (ans[i] == 1) { cout << i / 4 + 1 << " " << i % 4 + 1; cout << "\n"; } } return 0; } /* -+-- ---- ---- -+-- */