USACO Elite 2008 December Competition Silver
题意:给你一些正方形的拼图碎块,每个碎块有四个边,每边都有一个记号,分别是小写字母a-z。其中没有标记的边,也就是边界的边用'0'标记。题目给定一个矩阵,把这些碎块放进去,要求每个边相接的记号必须一样,边界上的边必须是'0'。
解法:DFS。这个操作起来还是挺麻烦的,做处理的时候要小心一些。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define Up num[0]
#define Right num[1]
#define Down num[2]
#define Left num[3]
char ca,cb,cc,cd;
int r,c,rc;
bool v[110];
class Jigsaw
{
public:
int serialNumber;
char num[4];
public:
void readIn()
{
scanf("%d%*c%c%*c%c%*c%c%*c%c%*c",&serialNumber,num,num+1,num+2,num+3);
}
void printOut()
{
printf("%d %c %c %c %c\n",serialNumber,num[0],num[1],num[2],num[3]);
}
int checkCorner()
{
int i;
for (i=0; i<4; i++)
{
if (num[i] == '0' && num[(i+1)%4] == '0')
return i;
}
return -1;
}
int checkSuit2c()
{
int i;
for (i=0; i<4; i++)
{
if (num[i] == ca && num[(i+1)%4] == cb)
return i;
}
return -1;
}
int checkSuit3c()
{
int i;
for (i=0; i<4; i++)
{
if (num[i] == ca && num[(i+1)%4] == cb && num[(i+2)%4] == cc)
return i;
}
return -1;
}
int checkSuit4c()
{
int i;
for (i=0; i<4; i++)
{
if (num[i] == ca && num[(i+1)%4] == cb && num[(i+3)%4] == cc)
return i;
}
return -1;
}
};
Jigsaw js[110];
Jigsaw tb[11][11];
bool check_and_rotate(int x,int y,int d)
{
int t;
if (x == 0 && y == 0)
{
t=js[d].checkCorner();
if (t == -1)
return false;
tb[x][y].serialNumber=js[d].serialNumber;
tb[x][y].Left=js[d].num[t];
tb[x][y].Up=js[d].num[(t+1)%4];
tb[x][y].Right=js[d].num[(t+2)%4];
tb[x][y].Down=js[d].num[(t+3)%4];
return true;
}
if (x == 0)
cb='0';
else
cb=tb[x-1][y].Down;
if (y == 0)
ca='0';
else
ca=tb[x][y-1].Right;
if (y == c-1)
{
cc='0';
t=js[d].checkSuit3c();
if (t == -1)
return false;
tb[x][y].serialNumber=js[d].serialNumber;
tb[x][y].Left=js[d].num[t];
tb[x][y].Up=js[d].num[(t+1)%4];
tb[x][y].Right=js[d].num[(t+2)%4];
tb[x][y].Down=js[d].num[(t+3)%4];
return true;
}
else if (x == r-1)
{
cc='0';
t=js[d].checkSuit4c();
if (t == -1)
return false;
tb[x][y].serialNumber=js[d].serialNumber;
tb[x][y].Left=js[d].num[t];
tb[x][y].Up=js[d].num[(t+1)%4];
tb[x][y].Right=js[d].num[(t+2)%4];
tb[x][y].Down=js[d].num[(t+3)%4];
return true;
}
else
{
t=js[d].checkSuit2c();
if (t == -1)
return false;
tb[x][y].serialNumber=js[d].serialNumber;
tb[x][y].Left=js[d].num[t];
tb[x][y].Up=js[d].num[(t+1)%4];
tb[x][y].Right=js[d].num[(t+2)%4];
tb[x][y].Down=js[d].num[(t+3)%4];
return true;
}
return false;
}
bool DFS(int x,int y)
{
int i,j;
if (y == c)
{
x++;
y=0;
if (x == r)
{
for (i=0; i<r; i++)
{
for (j=0; j<c; j++)
{
tb[i][j].printOut();
}
}
return true;
}
return DFS(x,y);
}
for (i=0; i<rc; i++)
{
if (v[i] == true)
continue;
if (check_and_rotate(x,y,i) == true)
{
v[i]=true;
if (DFS(x,y+1) == true)
return true;
v[i]=false;
}
}
return false;
}
int main()
{
int i,j;
scanf("%d%d",&r,&c);
rc=r*c;
for (i=0; i<rc; i++)
{
js[i].readIn();
v[i]=false;
}
DFS(0,0);
return 0;
}