# 牛客假日团队赛5J 护城河 bzoj 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘 （凸包的周长）

64bit IO Format: %lld

...
-----------------......
../..........
.............
./.........................
.........................
|........................
|.........................
|..........................

..........................|
.*........................|
.......................
..|
........................|
.........................
......................./.
......................../..
.......----------------...
（请复制到记事本中用等宽字体查看）

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

70.87

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/

const int MAX=5005;// 最大点数
const int INF=0x3f3f3f3f;//坐标的最大值
// 本模板读入默认是1-n读入
int n;
int top;
struct Node
{
int x,y;
}p[MAX],S[MAX];//p储存节点的位置，S是凸包的栈
inline bool cmp(Node a,Node b)//比较函数，对点的极角进行排序
{
double A=atan2((a.y-p[1].y),(a.x-p[1].x));
double B=atan2((b.y-p[1].y),(b.x-p[1].x));
if(A!=B)return A<B;
else    return a.x<b.x; //这里注意一下，如果极角相同，优先放x坐标更小的点
}
long long Cross(Node a,Node b,Node c)//计算叉积
{
return 1LL*(b.x-a.x)*(c.y-a.y)-1LL*(b.y-a.y)*(c.x-a.x);
}
void Get()//求出凸包
{
p[0]=(Node){INF,INF};int k;
for(int i=1;i<=n;++i)//找到最靠近左下的点
if(p[0].y>p[i].y||(p[0].y==p[i].y&&p[i].x<p[0].x))
{p[0]=p[i];k=i;}
swap(p[k],p[1]);
sort(&p[2],&p[n+1],cmp);//对于剩余点按照极角进行排序
S[0]=p[1],S[1]=p[2];top=1;//提前在栈中放入节点
for(int i=3;i<=n;)//枚举其他节点
{
if(top&&Cross(S[top-1],p[i],S[top])>=0)
top--;//如果当前栈顶不是凸包上的节点则弹出
else  S[++top]=p[i++];//加入凸包的栈中
}
//底下这个玩意用来输出凸包上点的坐标
//for(int i=0;i<=top;++i)
//    printf("(%d,%d)\n",S[i].x,S[i].y);
}
double  getdis(Node one ,Node two)
{
double res=sqrt((one.x-two.x)*(one.x-two.x)+(two.y-one.y)*(two.y-one.y));
return res;

}
double solve()// 返回凸包的边长 ___注意n=1,n=2时候的特判
{
double ans=0.00000000000000;
ans=ans+getdis(S[0],S[top]);
repd(i,1,top)
{
ans=ans+getdis(S[i],S[i-1]);
}
return ans;
}

int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
cin>>n;
repd(i,1,n)
{
cin>>p[i].x>>p[i].y;
}
Get();
cout<<fixed<<setprecision(2)<<solve()<<endl;
return 0;
}

inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}

posted @ 2019-08-01 18:17  茄子Min  阅读(100)  评论(0编辑  收藏  举报