nyist-78 圈水池(建立凸包)

題目鏈接:傳送門

78-圈水池

內存限制:64MB 時間限制:3s Special Judge: No

accepted:1 submit:1

題目描述:
有一個牧場,牧場上有很多個供水裝置,現在牧場的主人想要用籬笆把這些供水裝置圈起來,以防止不是自己的牲畜來喝水,各個水池都標有各自的座標,現在要你寫一個程序利用最短的籬笆將這些供水裝置圈起來!(籬笆足夠多,並且長度可變)

輸入描述:
第一行輸入的是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

思路:建立凸包。先排序,從小到大(也可以從大到小),可以將過程分爲兩步,先建立上半部分,再建立下半部分(思想是一樣的),因爲排完序後開頭和結尾的兩個點是一定有的,所以從開始點開始,查找差積小於等於0的(或者大於等於0的,這只是方向的問題,不影響結果),下半部分也是這樣。

代碼:

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

const int maxn=109;
struct node
{
    int x,y;
}edge[maxn],ans[maxn];

bool cmp(node a,node b)
{
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
int mul(node a,node b,node c)//計算差積
{
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}

int solve(int n)
{
    int len=0;
    for(int i=0;i<n;i++)//計算上半部分
    {
        while(len>1&&mul(ans[len-2],ans[len-1],edge[i])<=0) len--;
        ans[len++]=edge[i];
    }
    int k=len;
    for(int i=n-1;i>=0;i--)//計算下半部分
    {
        while(len>k&&mul(ans[len-2],ans[len-1],edge[i])<=0) len--;
        ans[len++]=edge[i];
    }
    return len-1;//最後一個是開始點(開始點被記錄了兩次)
}
int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d%d",&edge[i].x,&edge[i].y);

        sort(edge,edge+n,cmp);//排序

        int len=solve(n);
        sort(ans,ans+len,cmp);
        for(int i=0;i<len;i++)
            printf("%d %d\n",ans[i].x,ans[i].y);
    }
    return 0;
}
發佈了186 篇原創文章 · 獲贊 14 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章