题目链接: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; }