您的位置:首页 > 其它

zoj 3761 Easy billiards

2014-03-02 18:53 405 查看
题目可以抽象成:给你n个点,横坐标或纵坐标相同的 最接近的 点连起来,看作一条边。转换为图的遍历,操作就是返回路径。

dfs一遍求连通分量个数,再dfs一遍返回的时候输出对应操作。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;

const int N=20005;
struct Point{
int x,y,id;
}p
;
int cmp1(Point a,Point b){
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}
int cmp2(Point a,Point b){
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
int cmp3(Point a,Point b){
return a.id<b.id;
}

int start
,cnt,n,visit
;

struct Edge{
int v,next;
}e
;
void add(int u,int v){
e[cnt].v=v;
e[cnt].next=start[u];
start[u]=cnt++;
}

void dfs2(int x){
visit[x]=1;
for(int i=start[x];i!=-1;i=e[i].next){
int y=e[i].v;
if(!visit[y])
dfs2(y);
}
}

char vec[4][20]={"DOWN","UP","LEFT","RIGHT"};
void dfs(int pre,int x){
visit[x]=1;
for(int i=start[x];i!=-1;i=e[i].next){
int y=e[i].v;
if(!visit[y])
dfs(x,y);
}
if(pre==-1) return;
int t;//从x返回pre对应操作
if(p[pre].x==p[x].x){
if(p[pre].y<p[x].y)	t=0;
else	t=1;
}
else{
if(p[pre].x<p[x].x) t=2;
else t=3;
}
printf("(%d, %d) %s\n",p[x].x,p[x].y,vec[t]);
}
int main(){
while(cin>>n){
cnt=0;
memset(start,-1,sizeof start);
memset(visit,0,sizeof visit);
for(int i=1;i<=n;i++)
scanf("%d %d",&p[i].x,&p[i].y),p[i].id=i;
sort(p+1,p+n+1,cmp1);
for(int i=2;i<=n;i++){
if(p[i].x==p[i-1].x){
add(p[i].id,p[i-1].id);
add(p[i-1].id,p[i].id);
}
}
sort(p+1,p+n+1,cmp2);
for(int i=2;i<=n;i++){
if(p[i].y==p[i-1].y){
add(p[i].id,p[i-1].id);
add(p[i-1].id,p[i].id);
}
}
sort(p+1,p+n+1,cmp3);
int ans=0;
for(int i=1;i<=n;i++){
if(!visit[i])
ans++;dfs2(i);
}
printf("%d\n",ans);
memset(visit,0,sizeof visit);
for(int i=1;i<=n;i++){
if(!visit[i])
dfs(-1,i);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: