题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1008
题意:
哈特近来一直在玩有趣的 Gnome Tetravex 游戏。在游戏开始时,玩家会得到 n×n(n≤5) 个正方形。每个正方形都被分成 4个标有数字的三角形(数字的范围是 0到9)。这四个三角形分 别被称为“左三角形”、“右三角形”、“上三角形”和“下三角形”。例如,图 2.12(a)是2×2的正 方形的一个初始状态。
图2.12 Gnome Tetravex游戏 玩家需要重排正方形,到达目标状态。在目标状态中,任何两个相邻正方形的相邻三角形上 的数字都相同。图 2.12(b)是一个目标状态的例子。
判断是否有解。
题解:
DFS。一次确定每个格子填充什么样的方块。但是这样的话复杂度25!,TLE。为了能够减少时间,我们将相同类型的方块只保存一次,并且保存相同方块出现的次数。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX=6;
struct part
{
int l,r,u,d;
part(){};
part(int u,int r,int d,int l):u(u),r(r),d(d),l(l){};
bool operator ==(const part &tmp)
{
return tmp.l==l&&tmp.r==r&&tmp.u==u&&tmp.d==d;
}
};
part p[MAX*MAX];//记录输入的块
int sum[MAX*MAX];//每种块的个数
int g[MAX][MAX];
int n;
bool ans;
void dfs(int t)
{
if(t==n*n||ans)
{
ans=true;
return;
}
int x=t/n,y=t%n;
for(int i=0;i<n*n&&!ans;i++)
{
if(sum[i])
{
if(x>0)
if(p[i].u!=p[g[x-1][y]].d) continue;
if(y>0)
if(p[i].l!=p[g[x][y-1]].r) continue;
g[x][y]=i;
sum[i]--;
dfs(t+1);
sum[i]++;
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int tcase=1;
while(scanf("%d",&n)&&n)
{
if(tcase>1) printf("\n");
printf("Game %d: ",tcase++);
memset(sum,0,sizeof(sum));
for(int i=0;i<n*n;i++)
{
int l,r,u,d;
scanf("%d%d%d%d",&u,&r,&d,&l);
p[i]=part(u,r,d,l);
int flag=0;
for(int j=0;j<i;j++)
{
if(p[j]==p[i])
{
flag=1;
sum[j]++;
break;
}
}
if(!flag)
sum[i]++;
}
ans=false;
dfs(0);
printf("%s\n",ans?"Possible":"Impossible");
}
return 0;
}