[Elite 2008 Dec USACO]Jigsaw Puzzles

#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
",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;
}

USACO Elite 2008 December Competition Silver

题意:给你一些正方形的拼图碎块,每个碎块有四个边,每边都有一个记号,分别是小写字母a-z。其中没有标记的边,也就是边界的边用'0'标记。题目给定一个矩阵,把这些碎块放进去,要求每个边相接的记号必须一样,边界上的边必须是'0'。

解法:DFS。这个操作起来还是挺麻烦的,做处理的时候要小心一些。

原文地址:https://www.cnblogs.com/nbalive2001/p/6878236.html