BNUOJ 3881 Jigsaw Puzzles

来源:互联网 发布:原油数据公布的网站 编辑:程序博客网 时间:2024/06/05 00:34

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;}