• 【COGS & USACO】896. 圈奶牛(凸包)


    http://cojs.tk/cogs/problem/problem.php?pid=896

    我的计算几何入门题。。。

    看了看白书的计算几何部分,,恩好嘛。。

    乃们都用向量!!!!

    干嘛非要将2个点确定一条线变成一个点从原点o出发的射线!!!!

    这就是所谓的玩概念吗

    然后用所谓的向量加减,是这些向量起点相同,然后就变成了原点o出发的射线!!!

    然后你们还在玩概念!我跪了。

    (以上纯属蒟蒻吐槽)

    好吧,计算几何非常有用的。。简化了不少操作。

    这里还有啥点积啥叉积。点积就是同一起点的向量(终点)的 x坐标乘积+y坐标乘积,,,,叉积就是同一起点的向量(终点)的 x坐标和y坐标交叉乘起来的差。。

    噗。。真帅!!

    计算几何好神奇啊!!

    简化了好多操作!!!

    我发现我爱上他了!!

    (吐槽完毕)

    会到此题。。。裸的凸包。。

    白书上有,我就不说了,,就是扫过去判断叉积正负,也就是说在向量左边还是右边,在左边就继续,在右边就退栈重来。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <string>
    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; }
    
    using namespace std;
    
    void setio(string name){
    	string in = name + ".in", out = name + ".out";
    	ios::sync_with_stdio(false);
    	freopen(in.c_str(), "r", stdin);
    	freopen(out.c_str(), "w", stdout);
    }
    
    const int N=10005;
    struct node { 
    	double x, y; 
    	node(const double &_x=0, const double &_y=0) : x(_x), y(_y) {}
    }st[N], p[N];
    int cnt, n;
    node operator - (const node &a, const node &b) { return node(a.x-b.x, a.y-b.y); }
    double cross(const node &a, const node &b) { return a.x*b.y-b.x*a.y; }
    const bool cmp(const node &a, const node &b) { return (a.x==b.x)?(a.y<b.y):(a.x<b.x); }
    const double dis(const node &a, const node &b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); }
    void tubao() {
    	sort(p, p+n, cmp);
    	cnt=0;
    	rep(i, n) {
    		while(cnt>1 && cross(st[cnt-1]-st[cnt-2], p[i]-st[cnt-2])<=0) --cnt;
    		st[cnt++]=p[i];
    	}
    	int k=cnt;
    	for3(i, n-2, 0) {
    		while(cnt>k && cross(st[cnt-1]-st[cnt-2], p[i]-st[cnt-2])<=0) --cnt;
    		st[cnt++]=p[i];
    	}
    	if(n>1) --cnt;
    }
    
    int main() {
    	setio("fc");
    	scanf("%d", &n);
    	rep(i, n) scanf("%lf%lf", &p[i].x, &p[i].y);
    	tubao();
    	double ans=0;
    	for1(i, 0, cnt-1) ans+=dis(st[i], st[i+1]);
    	printf("%.2lf
    ", ans);
    	return 0;
    }
    

    描述

    农夫约翰想要建造一个围栏用来围住他的奶牛,可是他资金匮乏。他建造的围栏必须包括他的奶牛喜欢吃草的所有地点。对于给出的这些地点的坐标,计算最短的能够围住这些点的围栏的长度。

    PROGRAM NAME: fc

    INPUT FORMAT(file fc.in)

    输入数据的第一行包括一个整数 N。N(0 <= N <= 10,000)表示农夫约翰想要围住的放牧点的数目。接下来 N 行,每行由两个实数组成,Xi 和 Yi,对应平面上的放牧点坐标(-1,000,000 <= Xi,Yi <= 1,000,000)。数字用小数表示。

    OUTPUT FORMAT(file fc.out)

    输出必须包括一个实数,表示必须的围栏的长度。答案保留两位小数。

    SAMPLE INPUT (file fc.in)

    4
    4 8
    4 12
    5 9.3
    7 8 

    SAMPLE OUTPUT (file fc.out)

    12.00
  • 相关阅读:
    关于项目中 "不能创建大小为 8190 的行,该大小大于所允许的最大行大小 8060 "的处理
    sql 使用with 递归
    ssh,安全验证的级别(来自BD百科)
    Windows系统自带路由命令Route add,解决双网卡网络流向问题
    irreversiblecipher和cipher区别(华为交换机)
    Centos7重置root密码(20220527 02:03测试可用)
    2022中级财务管理相关公式的总结
    移动端软键盘顶出nav
    React.Component生命周期
    Axure 9 单选效果
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3931716.html
Copyright © 2020-2023  润新知