圈水池
时间限制:
3000 ms | 内存限制:
65535 KB
难度:
4
-
描述
- 有一个牧场,牧场上有很多个供水装置,现在牧场的主人想要用篱笆把这些供水装置圈起来,以防止不是自己的牲畜来喝水,各个水池都标有各自的坐标,现在要你写一个程序利用最短的篱笆将这些供水装置圈起来!(篱笆足够多,并且长度可变)
-
-
输入
-
第一行输入的是N,代表用N组测试数据(1<=N<=10)
第二行输入的是m,代表本组测试数据共有m个供水装置(3<=m<=100)
接下来m行代表的是各个供水装置的横纵坐标 -
输出
- 输出各个篱笆经过各个供水装置的坐标点,并且按照x轴坐标值从小到大输出,如果x轴坐标值相同,再安照y轴坐标值从小到大输出
-
样例输入
-
1 4 0 0 1 1 2 3 3 0
样例输出
-
0 0 2 3 3 0
-
第一行输入的是N,代表用N组测试数据(1<=N<=10)
Code:
一样的方法刚写过一个题, 跟 HDU 1348 和 POJ 1113 几乎是一模一样的
本来想水过的..大意了
我还以为第一次排序过后求出来的点就是有序的了..结果呢?WA了吧?
所以我把用队列存储改成了用数组存储,结束后排序一次就好了~
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
using namespace std;
typedef struct point
{
int x,y;
}point;
point v[105],res[105];
int vis[105],ver;
int cmp(point a,point b)
{
if(a.x < b.x) return 1;
else if(a.x == b.x)
{
if(a.y < b.y) return 1;
return 0;
}
return 0;
}
int calc(point a,point b,point c)//叉积
{
return (b.x-a.x)*(c.y-a.y) - (c.x-a.x)*(b.y-a.y);
}
double dis(point a,point b)
{
return sqrt((double)((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)));
}
double solve()
{
vis[0] = 1;
int in,i,bu,k=0;
in = 0;
res[k++] = v[in];
while(1)
{
bu = -1;
for(i=0;i<ver;i++)
{
if(!vis[i]) { bu = i; break; }
}
if(bu==-1) break;
for(i=0;i<ver;i++)
{
if(calc(v[in],v[bu],v[i])>0 || ( calc(v[in],v[bu],v[i])==0 && dis(v[in],v[i]) > dis(v[in],v[bu]) ))
bu = i;
}
if(vis[bu]) break;
res[k++] = v[bu];
vis[bu] = true;
in = bu;
}
sort(res,res+k,cmp);//这里这里!!!
for(i=0;i<k;i++)
printf("%d %d\n",res[i].x,res[i].y);
}
int main()
{
int i,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&ver);
for(i=0;i<ver;i++)
scanf("%d%d",&v[i].x,&v[i].y);
sort(v,v+ver,cmp);
memset(vis,0,sizeof(vis));
solve();
}
return 0;
}