ZOJ 1079 Robotic Jigsaw

 Statement of the Problem

Your task here is to write a program to aid in the assembly of a jigsaw puzzle by a robot.

The puzzle is a rectangular array of flat four-sided pieces. Except for the outer borders, each side of each piece is shaped in such a way that it matches one side of exactly one other piece.

When the puzzle is presented to the robot, all the pieces are scrambled and spread out on a table, face up, in front of the robot's camera eye. Let's assume that someone already wrote some software that does the image processing part of the problem: find the puzzle pieces in the image captured by the camera, break the outline of each piece into its four sides, and find pairs of sides that have the same shape. Your task is to program the next step - namely, decide where in the grid each piece should be placed, and how it should be rotated.

The image-processing software assigns, to each piece that the robot sees on the table, a unique piece number between 0 and N-1, in some arbitrary order. It also labels the sides of the piece with integers 0, 1, 2, 3, in counterclockwise order, starting from an arbitrary side:


Input Format

The input contains several consecutive instances of the problem. Each instance consists of: one line containing two integers N, 0 < N < 500 (the number of pieces) and K; the come K lines, one for each pair of similar sides that were found among all pieces seen by the robot, in arbitrary order. Each of these lines contains four integers like this:

17 2 23 1

This line says that side number 2 of piece number 17 fits side 1 of piece 23. Therefore, in the assembled puzzle, pieces 17 and 23 should be neighbors, in one of these four positions:


You can assume that the input data includes enough information to assemble the puzzle completely. Note, however, that it may not include all pairs of matching sides, and it may include some redundant pairs that could be deduced from the previous ones. The end of the input is marked by a line containing a single 0.

Output Format

For the ith instance of the input file you should write the line Instance i:, followed by a sequence of N lines, one for each piece, containing four integers such as 6 9 17 2. This line says that piece number 17 should be placed in row 6 and column 9 of the grid, turned so that its side number 2 lies at the bottom. (By convention, rows are numbered from top to bottom, and columns from left to right, starting with 0.)

Note also that any solution can be turned by multiples of 90 degrees to give three other valid solutions. In order to make the output unique, your must turn your solution around so that piece number 0 has its side number 0 at the bottom (turned towards the robot). In any case, the upper left corner of the assembled puzzle should be at position [0, 0].

The lines of the output should be presented in lexicographic order of the rows and columns, as shown in the sample output.

Sample Input

12 13
0 0 5 0
0 2 6 2
1 2 11 0
1 3 9 2
2 0 5 1
2 1 4 2
3 0 10 3
3 3 8 0
4 0 7 1
4 1 11 1
6 1 7 2
8 2 9 3
10 0 11 2
0

Sample Output

Instance 1:
    0    0     3 3
    0    1    10 0
    0    2     7 1
    0    3     6 2
    1    0     8 2
    1    1    11 0
    1    2     4 2
    1    3     0 0
    2    0     9 1
    2    1     1 0
    2    2     2 3
    2    3     5 2



#include <iostream>
#include <string.h>
#include<algorithm>
#include <iomanip>
using namespace std;
int dx[4]= {1,0,-1,0};
int dy[4]= {0,1,0,-1};
int queue[501];
int used[500];
struct
{
    int id;
    int side;
} piece[500][4];
struct position
{
    int x,y;
    int id;
    int side;
} pos[500];
int compare(const void *a,const void *b)
{
    int c;
    if((c=(((struct position*)a)->x-((struct position*)b)->x))!=0)
        return c;
    return ((((struct position*)a)->y-((struct position*)b)->y));
}
int main()
{
    int n,k;
    int i;
    int cases= 1;
    while(cin>>n&&n)
    {
        cin>>k;
        memset(piece,255,sizeof(piece));
        memset(used,0,sizeof(used));
        int a,b,c,d;
        for(i=0; i<k; i++)
        {
            cin>>a>>b>>c>>d;
            piece[a][b].id=c;
            piece[a][b].side=d;
            piece[c][d].id=a;
            piece[c][d].side=b;
        }
        for(i=0; i<n; i++)
        {
            pos[i].id=i;
        }
        pos[0].x=0;
        pos[0].y=0;
        pos[0].side=0;
        int first=0,count=0;
        queue[0]=0;
        used[0]=1;
        while (first<=count)
        {
            a=queue[first];
            int x0=pos[a].x,y0=pos[a].y;
            d=pos[a].side;
            int number;
            for(i=0; i<4; i++)
                if((number=piece[a][i].id)>=0)
                    if(used[number]==0)
                    {
                        b=piece[a][i].side;
                        used[number]=1;
                        pos[number].x=x0+dx[(i-d)&3] ;         //(i-d)&3相当于(x+4)%4
                        pos[number].y=y0+dy[(i-d)&3];
                        pos[number].side=((b-i+d+2))&3;
                        queue[++count]=number;
                    }
            first++;
        }
        qsort(pos,n,sizeof(position),&compare);
        a=pos[0].x;
        b=pos[0].y;
        cout<<"Intance "<<cases++<<":"<<endl;
        for(i=0; i<n; i++)
            cout<<setw(5)<<pos[i].x-a<<setw(5)<<pos[i].y-b<<setw(6)<<pos[i].id<<setw(2)<<pos[i].side<<endl;
    }
    return 0;
}






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的Anthony

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值