http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=8
题目意思很简单,数据量也比较小,只需用dfs即可,不过还是需要剪纸,对于相同的类型的卡片记录数量,这样才不会超时。对于每一次放置的时候我们都要判断放置是不是合法,则个只需要通过一个简单的上左判断即可。程序如下:
/*
ID: chenan
PROG: zoj 1008 Gnome Tetravex
LANG: C++
*/
#include<iostream>
#include<string.h>
#include<stdio.h>
const int maxn = 30 ;
struct Point{
int left ;
int right ;
int up ;
int down ;
bool operator == (Point x)
{
if(left == x.left && right == x.right && up == x.up && down == x.down)
return true ;
return false ;
}
}point[maxn];
int vis[maxn] ;
int map[maxn][maxn] ;
int find_index(Point p) ;
bool input() ;
bool dfs(int ) ;
bool judge(int , int) ;
int n ;
int m ;
int main()
{
int test ;
test = 1 ;
while(input())
{
int i ;
bool flag ;
int cnt ;
flag = 0 ;
memset(map , -1 , sizeof(map)) ;
cnt = 0 ;
flag = dfs(0) ;
if(test > 1)
printf("\n") ;
if(flag)
printf("Game %d: Possible\n" , test) ;
else
printf("Game %d: Impossible\n" ,test) ;
test ++ ;
}
//system("pause") ;
return 0 ;
}
bool input()
{
scanf("%d" , &n) ;
if(n==0)
return 0 ;
int i ;
int j ;
Point p ;
m = 0 ;
memset(vis , 0 , sizeof(vis)) ;
for(i = 0 ; i < n * n ; i ++)
{
scanf("%d %d %d %d" , &p.up , &p.right , &p.down , &p.left) ;
j = find_index(p) ;
if(j == m)
{
point[j] = p ;
m ++ ;
}
vis[j] ++ ;
}
return 1 ;
}
int find_index(Point p)
{
int i ;
Point q ;
for(i = 0 ; i < m ; i ++)
{
if(point[i] == p)
return i ;
}
return m ;
}
bool dfs(int lay)
{
if(lay == n * n)
return true ;
int i ;
int j ;
for(i = 0 ; i < m ; i ++)
{
if(vis[i]&&judge(lay , i))
{
vis[i] -- ;
map[lay/n][lay%n] = i ;
if(dfs(lay + 1 ))
return true ;
map[lay/n][lay%n] = -1 ;
vis[i] ++ ;
}
}
return false ;
}
bool judge(int lay , int x)
{
int y ;
if(lay / n)
{
y = map[lay / n - 1][lay % n] ;
if(point[x].up != point[y].down)
return false ;
}
if(lay % n)
{
y = map[lay/n][lay%n-1] ;
if(point[x].left != point[y].right)
return false ;
}
return true ;
}