Gnome Tetravex
题意:有N*N个方格,每个方格分为上下左右四个部分,每个部分填数字。现在要求重排方块,使得每两个有边相连的方块对应的数字相同。
思路:就是一个简单的搜索,我想了个剪枝,将上下左右四个方向上每个数字对应的是哪几个方块记录下来,但是这个剪枝并没有起很大的作用,还是T了。后来才发现,如果有很多个方块是相同的,会重复搜索,所以需要将相同的方块一起处理,用一个sum[]值来表示该种方块的数目。
代码:
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<fstream>
#include<cstring>
#include<ctype.h>
#include<iostream>
#include<algorithm>
#define INF (1<<30)
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))
#define rep(i, n) for (int i = 0; i < n; i++)
#define debug puts("===============")
typedef long long ll;
using namespace std;
struct node {
int x[4];
bool operator == (const node &T) const {
for (int i = 0; i < 4; i++) if (x[i] != T.x[i]) return false;
return true;
}
}e[26];
vector<int> T[4][10];
int n;
bool flag = false;
int a[30];
int sum[30];
void dfs(int t) {
if (flag) return ;
if (t == n * n) {
flag = true;
return ;
}
if (t < n) {
int u = e[a[t - 1]].x[1];
for (int i = 0; i < T[3][u].size(); i++) {
int v = T[3][u][i];
if (sum[v] > 0) {
sum[v]--, a[t] = v;
dfs(t + 1);
if (flag) return ;
sum[v]++;
}
}
}
else {
int u = e[a[t - n]].x[2];
for (int i = 0; i < T[0][u].size(); i++) {
int v = T[0][u][i];
if (sum[v] > 0) {
bool ok = true;
if (t % n) {
if (e[a[t - 1]].x[1] != e[v].x[3]) ok = false;
}
if (ok) {
sum[v]--, a[t] = v;
dfs(t + 1);
if (flag) return ;
sum[v]++;
}
}
}
}
return ;
}
int main () {
int cnt = 1;
while(~scanf("%d", &n), n) {
if (cnt != 1) puts("");
rep(i, 10) {
rep(j, 4) {
T[j][i].clear();
}
}
int x;
memset(sum, 0, sizeof(sum));
rep(i, n * n) {
rep(j, 4) {
scanf("%d", &x);
e[i].x[j] = x;
T[j][x].push_back(i);
}
int k;
for (k = 0; k < i; k++) if (e[k] == e[i]) {
sum[k]++;
break;
}
if (k == i) {
sum[k]++;
}
}
flag = false;
for (int i = 0; i < n * n; i++) if (sum[i]) {
sum[i]--;
a[0] = i;
dfs(1);
if (flag) break;
sum[i]++;
}
printf("Game %d: ", cnt);
if (!flag) puts("Impossible");
else puts("Possible");
cnt++;
}
return 0;
}