ZOJ 3761 Easy billiards(並查集+樹遍歷)

E - Easy billiards
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu
Appoint description: 

Description

Edward think a game of billiards is too long and boring. So he invented a new game called Easy billiards.

Easy billiards has N balls on a brimless rectangular table in the beginning, and your goal is try to make the number of balls on the table as least as possible by several hit under the following rules:

1: The direction you hit the balls should parallel to the tables border.

2: If ball A crashed into ball B, ball B will moves in the same direction of ball A before the crashing, and ball A will stop in the place of ball B before the crashing.

3: If ball C is moving and there are no balls in front of ball C, it will runs out of the tables border, that means ball C is out of the table.

4: You can choose arbitrary ball on the table to hit, but on a hit, you can't let the ball you choose to hit runs out of the tables border. In another word, a ball could runs out of the table if and only if it was crashed by another ball in a hitting.

Now, Edward wants to know the least number of balls remained on the table after several hits, and how.

Input

There are multiple test cases. For each test cases, in the first line, there is an integer N, which means the number of the balls on the table. There are following N lines, each line contains two integers Xi and Yi, which means the coordinate of ball I. (0<=N<=2000, 0<=Xi,Yi<=10^8)

Output

For each test cases, you should output the least number of balls on the first line. And you should output several lines to show the order of hits following the first line, each line should contains the coordinate of the ball you choose to hit and the direction you hit. (LEFT,RIGHT,UP,DOWN).

Sample Input

4
0 0
2 0
4 0
2 2
9
1 1
2 1
3 1
1 2
2 2
3 2
1 3
2 3
3 3

Sample output

1
(2, 2) DOWN
(4, 0) LEFT
(2, 0) LEFT
1
(1, 3) DOWN
(1, 2) DOWN
(2, 3) DOWN
(2, 2) DOWN
(3, 3) DOWN
(3, 2) DOWN
(3, 1) LEFT
(2, 1) LEFT

題意:檯面有很多小球,每次讓小球撞擊四個方向任意一個的另外一個小球,要求最後在臺面的球最少

 題解:把小球用並查集處理成很多個聯通塊,並連邊,然後進行dfs遍歷樹圖,讓子節點撞擊父節點即可


#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
struct point{
    int x,y;
}p[2008];
vector<int>g[2008];
int n,ans,i,j,x,y,res;
int fa[2008],mark[2008];
int myfind(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=myfind(fa[x]);
}
void dfs(int x,int f)
{
    mark[x]=1;
    for(vector<int>::iterator it=g[x].begin();it!=g[x].end();it++)
    {
        if(*it==f||mark[*it]) continue;
        dfs(*it,x);
    }
    if(f!=-1)
    {
        printf("(%d, %d) ",p[x].x,p[x].y);
        if(p[x].x==p[f].x)
        {
            if(p[x].y>p[f].y) printf("DOWN\n");
            else printf("UP\n");
        }
        else
        {
            if(p[x].x>p[f].x) printf("LEFT\n");
            else printf("RIGHT\n");
        }
    }
}
int main()
{
    freopen("t.txt","r",stdin);
    while(scanf("%d",&n)>0)
    {
        for(i=1;i<=n;i++){ fa[i]=i; g[i].clear(); }
        res=n;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            for(j=1;j<i;j++)
            {
                if(p[i].x==p[j].x||p[i].y==p[j].y)
                {
                    g[i].push_back(j);
                    g[j].push_back(i);
                    x=myfind(i); y=myfind(j);
                    if(x!=y) fa[x]=y,res--;
                }
            }
        }
        memset(mark,0,sizeof(mark));
        printf("%d\n",res);
        for(i=1;i<=n;i++) if(fa[i]==i) dfs(i,-1);
    }

    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章