【BZOJ】1670:[Usaco 2006 Oct]Building the Moat堀の掘削(凸包)
3797 ワード
http://www.lydsy.com/JudgeOnline/problem.php?id=1670
裸で凸包を打った.
Description
喉が渇いた蟻食い獣が農場に入るのを防ぐため、Farmer Johnは農場の周りに堀を掘ることにした.農場には全部でN(8<=N<=5000)株の泉があり、また、堀はいつも川にまっすぐにつながっている隣接する2本の泉である.堀はすべての泉を守らなければならない.つまり、すべての泉を囲むことができる.泉の水はきっと堀の内部にあるか、ちょうど川の上にあるに違いない.もちろん、堀は閉鎖的な環を構成しています.堀を掘るのは高価な工事なので、節約したFJは堀の全長をできるだけ小さくしてほしいと思っています.需要を満たす条件の下で、堀の総長が一番小さいかどうかを計算するプログラムを書いてください.すべての泉の座標は(1億1000万、1億1000万、1億1000万)の範囲の整点にあり、1本の泉は唯一確定した座標に対応している.そして、任意の3つの泉は一直線上にありません.以下は20本の泉を含む地図で、泉は「*」で表されています.
図の直線は、堀を守る最良の掘削案であり、すべての泉を囲むことができる最短ルートである.ルートは左上から,泉水を通る座標は,(18,0),(6,−6),(0,−5),(−3,−3),(−17,0),(−7,7),(0,4),(3,3)の順であった.1週間の迂回経路の長さは70.87056850888(...)である.答えは2桁の小数を残すだけで、出力は70.87です.
Input
*1行目:1つの整数、N*2.N+1行目:行ごとに2つのスペースで区切られた整数、x[i]とy[i]、すなわちi番目の泉の位置座標を含む
Output
*1行目:条件を満たす堀の最短長さを示す数字を出力します.小数を2桁保持
Sample Input
20
2 10
3 7
22 15
12 11
20 3
28 9
1 12
9 3
14 14
25 6
8 1
25 1
28 4
24 12
4 15
13 5
26 5
21 11
24 4
1 8
Sample Output
70.87
HINT
Source
ポンチシェル
裸で凸包を打った.
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << #x << " = " << x << endl
#define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }
const int N=6005;
struct point { double x, y; }a[N], s[N];
typedef point dat;
dat operator-(const point &a, const point &b) { return (dat){a.x-b.x, a.y-b.y}; }
double cross(const dat &a, const dat &b) { return a.x*b.y-a.y*b.x; }
bool cmp(const point &a, const point &b) { return a.x==b.x?a.y<b.y:a.x<b.x; }
int top, n;
double ans;
void getans() {
sort(a+1, a+n+1, cmp);
for1(i, 1, n) {
while(top>1 && cross(s[top]-s[top-1], a[i]-s[top-1])<=0) --top;
s[++top]=a[i];
}
int t=top;
for3(i, n-1, 1) {
while(top>t && cross(s[top]-s[top-1], a[i]-s[top-1])<=0) --top;
s[++top]=a[i];
}
if(n>1) --top;
}
inline double dis(const point &a, const point &b) { return (double)sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); }
int main() {
read(n);
for1(i, 1, n) read(a[i].x), read(a[i].y);
getans();
for1(i, 1, top) ans+=dis(s[i], s[i+1]);
printf("%.2lf", ans);
return 0;
}
Description
喉が渇いた蟻食い獣が農場に入るのを防ぐため、Farmer Johnは農場の周りに堀を掘ることにした.農場には全部でN(8<=N<=5000)株の泉があり、また、堀はいつも川にまっすぐにつながっている隣接する2本の泉である.堀はすべての泉を守らなければならない.つまり、すべての泉を囲むことができる.泉の水はきっと堀の内部にあるか、ちょうど川の上にあるに違いない.もちろん、堀は閉鎖的な環を構成しています.堀を掘るのは高価な工事なので、節約したFJは堀の全長をできるだけ小さくしてほしいと思っています.需要を満たす条件の下で、堀の総長が一番小さいかどうかを計算するプログラムを書いてください.すべての泉の座標は(1億1000万、1億1000万、1億1000万)の範囲の整点にあり、1本の泉は唯一確定した座標に対応している.そして、任意の3つの泉は一直線上にありません.以下は20本の泉を含む地図で、泉は「*」で表されています.
図の直線は、堀を守る最良の掘削案であり、すべての泉を囲むことができる最短ルートである.ルートは左上から,泉水を通る座標は,(18,0),(6,−6),(0,−5),(−3,−3),(−17,0),(−7,7),(0,4),(3,3)の順であった.1週間の迂回経路の長さは70.87056850888(...)である.答えは2桁の小数を残すだけで、出力は70.87です.
Input
*1行目:1つの整数、N*2.N+1行目:行ごとに2つのスペースで区切られた整数、x[i]とy[i]、すなわちi番目の泉の位置座標を含む
Output
*1行目:条件を満たす堀の最短長さを示す数字を出力します.小数を2桁保持
Sample Input
20
2 10
3 7
22 15
12 11
20 3
28 9
1 12
9 3
14 14
25 6
8 1
25 1
28 4
24 12
4 15
13 5
26 5
21 11
24 4
1 8
Sample Output
70.87
HINT
Source
ポンチシェル