码迷,mamicode.com
首页 > 其他好文 > 详细

P3829 [SHOI2012]信用卡凸包

时间:2020-05-02 18:40:30      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:while   pac   false   信用卡   部分   sign   size   rtt   out   

还是不会计算几何。。

显然你需要 rotate 一下向量,学到许多。。

最后加上圆的周长就好了,因为并起来的部分是一个正圆。

// by Isaunoya
#include<bits/stdc++.h>
using namespace std;
const double pi = acos(-1);
const double eps = 1e-4;

struct Vector {
	double x, y;
	Vector (double _x = 0, double _y = 0) { x = _x, y = _y; }
	Vector operator + (const Vector & rhs) const { return Vector(x + rhs.x, y + rhs.y); }
	Vector operator - (const Vector & rhs) const { return Vector(x - rhs.x, y - rhs.y); }
	double operator ^ (const Vector & rhs) const { return x * rhs.y - y * rhs.x; }
	double dis() { return sqrt(x * x + y * y); }
	bool operator < (const Vector & rhs) const { return x == rhs.x ? y < rhs.y : x < rhs.x;  }
};

Vector rtt(Vector x, double tht) { return Vector(x.x * cos(tht) - x.y * sin(tht), x.x * sin(tht) + x.y * cos(tht)); }
int n; double a, b, r;
vector <Vector> p;

signed main() {
	ios :: sync_with_stdio(false);
	cin.tie(nullptr), cout.tie(nullptr);
	cin >> n;
	cin >> a >> b >> r;
	static Vector w[5];
	
	w[0] = Vector(-0.5 * b + r, 0.5 * a - r);
	w[1] = Vector(0.5 * b - r, 0.5 * a - r);
	w[2] = Vector(0.5 * b - r, -0.5 * a + r);
	w[3] = Vector(-0.5 * b + r, -0.5 * a + r);
	
	for(int i = 1 ; i <= n ; i ++) {
		double x, y, tht;
		cin >> x >> y >> tht;
		x += eps, y += eps, tht += eps; 
		Vector tmp = Vector(x, y);
		for(int j = 0 ; j < 4 ; j ++) { p.push_back(tmp + rtt(w[j], tht)); }
	}
	int sz = p.size() - 1;
	sort(p.begin(), p.end());
	static int st[233333], top = 0;
	st[++ top] = 0, st[++ top] = 1;
	auto ins = [&](int x) {
		while(top >= 2 && ((p[st[top - 1]] - p[st[top]]) ^ (p[st[top]] - p[x])) <= 0) -- top;
		st[++ top] = x;
	};
	double ans = 0;
	for(int i = 2 ; i <= sz ; i ++) { ins(i); }
	for(int i = 2 ; i <= top ; i ++) ans += (p[st[i]] - p[st[i - 1]]).dis();
	st[top = 1] = sz, st[++ top] = sz - 1;
	for(int i = sz - 2 ; ~i ; -- i) { ins(i); }
	for(int i = 2 ; i <= top ; i ++) ans += (p[st[i]] - p[st[i - 1]]).dis();
	ans += pi * 2 * r;
	cout << fixed << setprecision(2) << ans << ‘\n‘;
	return 0;
}

P3829 [SHOI2012]信用卡凸包

标签:while   pac   false   信用卡   部分   sign   size   rtt   out   

原文地址:https://www.cnblogs.com/Isaunoya/p/12818983.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!