http://poj.org/problem?id=2965
题意:4*4的01方阵,每次翻转一行和一列(交点只翻一次),求把所有面都翻成1的最小方案,多解输出任意一解。
直接暴力模拟:
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<string>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
char cg[4][4];
char g[4][4];
int tx[17], ty[17], ttop;
int ax[17], ay[17], atop;
inline bool less1(int k) {
int cnt = 0;
while(k) {
if(k & 1)
++cnt;
k >>= 1;
}
return cnt < atop;
}
inline void flip(int k) {
ttop = 0;
int cnt = 0;
while(k) {
if(k & 1) {
++ttop;
register int ri = tx[ttop] = cnt / 4;
register int rj = ty[ttop] = cnt % 4;
for(register int j = 0; j < 4; ++j) {
g[ri][j] = !g[ri][j];
}
for(register int i = 0; i < 4; ++i) {
g[i][rj] = !g[i][rj];
}
g[ri][rj] = !g[ri][rj];
}
k >>= 1;
++cnt;
}
return;
}
inline bool check() {
for(int i = 0; i < 4; ++i) {
for(int j = 0; j < 4; ++j) {
if(!g[i][j])
return 0;
}
}
return 1;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
while(~scanf("%s", cg[0])) {
for(int j = 0; j < 4; ++j) {
cg[0][j] = (cg[0][j] == '-');
}
for(int i = 1; i < 4; ++i) {
scanf("%s", cg[i]);
for(int j = 0; j < 4; ++j) {
cg[i][j] = (cg[i][j] == '-');
}
}
atop = 17;
for(int k = 0; k < 1 << 16; ++k) {
if(less1(k)) {
memcpy(g, cg, sizeof(g));
flip(k);
if(check()) {
atop = ttop;
memcpy(ax, tx, sizeof(ax));
memcpy(ay, ty, sizeof(ay));
}
}
}
printf("%d
", atop);
for(int i = 1; i <= atop; ++i) {
printf("%d %d
", ax[i] + 1, ay[i] + 1);
}
}
}
时间有点卡,可能多亏了剪枝才能过。