3743 -- LL’s cake

  搞了好久都过不了,看了下题解是用PSLG来做的。POJ 2164 && LA 3218 Find the Border (Geometry, PSLG 平面直线图) - LyonLys - 博客园 这篇里面写过一下,就是把点都提取出来,然后模拟沿着边界移动,找到多边形并计算面积。

  而我的做法是直接模拟多边形切割,各种超时爆内存。先留着,看以后能不能用这个来过。

没过的代码:

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue> using namespace std; const double EPS = 1e-;
inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
Point operator + (Point a) { return Point(x + a.x, y + a.y);}
Point operator - (Point a) { return Point(x - a.x, y - a.y);}
Point operator * (double p) { return Point(x * p, y * p);}
Point operator / (double p) { return Point(x / p, y / p);}
bool operator < (Point a) const { return sgn(x - a.x) < || sgn(x - a.x) == && y < a.y;}
bool operator == (Point a) const { return sgn(x - a.x) == && sgn(y - a.y) == ;}
} ; inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
inline double veclen(Point x) { return sqrt(dot(x, x));}
inline Point normal(Point x) { return Point(-x.y, x.x) / veclen(x);}
inline Point vecunit(Point x) { return x / veclen(x);} struct Line {
Point s, t;
Line() {}
Line(Point s, Point t) : s(s), t(t) {}
Point vec() { return t - s;}
Point point(double x) { return s + vec() * x;}
} ;
inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
inline bool onseg(Point x, Point s, Point t) { return sgn(cross(s - x, t - x)) == && sgn(dot(s - x, t - x)) < ;}
inline bool onseg(Point x, Line a) { return onseg(x, a.s, a.t);} struct Circle {
Point c;
double r;
Circle() {}
Circle(Point c, double r) : c(c), r(r) {}
bool in(Point x) { return sgn(veclen(x - c) - r) <= ;}
Point point(double x) { return Point(c.x + cos(x) * r, c.y + sin(x) * r);}
} ;
const double R = 10.0;
Circle cake = Circle(Point(0.0, 0.0), R);
const double PI = acos(-1.0);
template<class T> T sqr(T x) { return x * x;}
inline double angle(Point x) { return atan2(x.y, x.x);} int clint(Line s, Point *sol) {
Point nor = normal(s.vec()), ip = llint(s, Line(cake.c, cake.c + nor));
double dis = veclen(cake.c - ip);
if (sgn(dis - cake.r) >= ) return ;
Point dxy = vecunit(s.vec()) * sqrt(sqr(cake.r) - sqr(dis));
int ret = ;
sol[ret] = ip + dxy;
if (onseg(sol[ret], s)) ret++;
sol[ret] = ip - dxy;
if (onseg(sol[ret], s)) ret++;
return ret;
} double getsec(Point a, Point b) {
double a1 = angle(a - cake.c);
double a2 = angle(b - cake.c);
double da = fabs(a1 - a2);
if (da > PI) da = PI * 2.0 - da;
return sqr(cake.r) * da * sgn(cross(a - cake.c, b - cake.c)) / 2.0;
} inline double gettri(Point a, Point b) { return cross(a - cake.c, b - cake.c) / 2.0;}
//typedef vector<Point> VP;
const int N = ;
struct VP {
Point vex[N];
int n;
void clear() { n = ;}
void push_back(Point x) { vex[n++] = x;}
void pop_back() { n--;}
int size() { return n;}
} ; double cpint(VP pt) {
double ret = 0.0;
int n = pt.size();
Point tmp[];
pt.vex[n] = pt.vex[];
for (int i = ; i < n; i++) {
int ic = clint(Line(pt.vex[i], pt.vex[i + ]), tmp);
if (ic == ) {
if (!cake.in(pt.vex[i]) || !cake.in(pt.vex[i + ])) ret += getsec(pt.vex[i], pt.vex[i + ]);
else ret += gettri(pt.vex[i], pt.vex[i + ]);
} else if (ic == ) {
if (cake.in(pt.vex[i])) ret += gettri(pt.vex[i], tmp[]), ret += getsec(tmp[], pt.vex[i + ]);
else ret += getsec(pt.vex[i], tmp[]), ret += gettri(tmp[], pt.vex[i + ]);
} else {
if (pt.vex[i] < pt.vex[i + ] ^ tmp[] < tmp[]) swap(tmp[], tmp[]);
ret += getsec(pt.vex[i], tmp[]);
ret += gettri(tmp[], tmp[]);
ret += getsec(tmp[], pt.vex[i + ]);
}
// cout << "~~ic " << ic << ' ' << ret << endl;
}
return fabs(ret);
} bool fixpoly(VP &poly) {
double sum = 0.0;
int n = poly.size();
poly.vex[n] = poly.vex[];
for (int i = ; i < n; i++) sum += cross(poly.vex[i], poly.vex[i + ]);
if (sgn(sum) == ) return false;
if (sgn(sum) < ) reverse(poly.vex, poly.vex + n);
return true;
} void cutpoly(VP &poly, Line l, VP &ret) {
ret.clear();
int n = poly.size();
// cout << n << endl;
poly.vex[n] = poly.vex[];
for (int i = ; i < n; i++) {
if (sgn(cross(l.vec(), poly.vex[i] - l.s)) >= ) ret.push_back(poly.vex[i]);
if (sgn(cross(l.vec(), poly.vex[i] - poly.vex[i + ]))) {
Point ip = llint(l, Line(poly.vex[i], poly.vex[i + ]));
// cout << "ip " << ip.x << ' ' << ip.y << endl;
if (onseg(ip, poly.vex[i], poly.vex[i + ]) || poly.vex[i] == ip) ret.push_back(ip);
}
}
// cout << "cp sz " << ret.size() << endl;
} const int M = ;
int q[], qh, qt, nu;
VP rec[M];
queue<int> recycle; int getID() {
int ret;
if (nu >= M) {
if (recycle.empty()) { puts("shit!"); while () ;}
ret = recycle.front();
recycle.pop();
} else ret = nu++;
return ret;
} void retID(int x) { recycle.push(x);} int main() {
// freopen("in", "r", stdin);
// freopen("out", "w", stdout);
int T, n, tmp;
double x, y;
cin >> T;
while (T-- && cin >> n) {
while (!recycle.empty()) recycle.pop();
qh = qt = nu = ;
tmp = getID();
rec[tmp].clear();
rec[tmp].push_back(Point(-R * 2.0, -R * 2.0));
rec[tmp].push_back(Point(R * 2.0, -R * 2.0));
rec[tmp].push_back(Point(R * 2.0, R * 2.0));
rec[tmp].push_back(Point(-R * 2.0, R * 2.0));
fixpoly(rec[tmp]);
q[qt++] = tmp;
for (int i = ; i < n; i++) {
cin >> x >> y;
int sz = qt - qh;
Line t = Line(cake.point(x), cake.point(y));
// cout << cake.point(x).x << '=' << cake.point(x).y << endl;
// cout << cake.point(y).x << '~' << cake.point(y).y << endl;
for (int j = ; j < sz; j++) {
tmp = getID();
// cout << "qh ?? " << qh << ' ' << q[qh] << ' ' << rec[q[qh]].size() << endl;
cutpoly(rec[q[qh]], t, rec[tmp]);
if (fixpoly(rec[tmp])) {
// cout << j << "~~1 " << rec[tmp].size() << endl;
// for (int k = 0; k < rec[tmp].size(); k++) cout << rec[tmp].vex[k].x << ' ' << rec[tmp].vex[k].y << endl;
q[qt++] = tmp;
}
swap(t.s, t.t);
tmp = getID();
cutpoly(rec[q[qh]], t, rec[tmp]);
if (fixpoly(rec[tmp])) {
// cout << j << "~~2 " << rec[tmp].size() << endl;
// for (int k = 0; k < rec[tmp].size(); k++) cout << rec[tmp].vex[k].x << ' ' << rec[tmp].vex[k].y << endl;
q[qt++] = tmp;
}
retID(q[qh++]);
}
// cout << "sz~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " << qt - qh << endl;
}
double mx = 0.0;
while (qh < qt) {
mx = max(mx, cpint(rec[q[qh++]]));
// cout << ".. " << mx << endl;
}
printf("%.2f\n", mx);
}
return ;
} /*
6
2
-3.140000 0.000000
-1.000000 1.000000
2
-3.141592 0.000000
-1.570796 1.570796
3
-3.000000 3.000000
-2.000000 2.000000
-1.000000 1.000000
4
-3.140000 0.000000
-1.000000 1.000000
-3.140000 -1.000000
1.000000 0.000000
6
-3.140000 0.000000
-1.000000 1.000000
-3.140000 -1.000000
1.000000 0.000000
-3.140000 -1.000000
1.000000 0.000000
6
-3.141592 0.000000
-1.570796 1.570796
-3.141592 -1.570796
0.000000 1.570796
-3.141592 1.570796
0.000000 -1.570796
*/

PSLG的方法将尽快更新上来!

UPD:

  模拟遍历边界,985ms压线过,因为有圆弧,所以有几个特判。比较好奇别人那些稳稳的不超时除了少用了STL还做了些什么?

代码如下:

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <set> using namespace std; const double EPS = 1e-;
inline int sgn(double x) { return (x > EPS) - (x < -EPS);} struct Point {
double x, y;
int id;
Point() {}
Point(double x, double y) : x(x), y(y) {}
bool operator < (Point a) const { return sgn(x - a.x) < || sgn(x - a.x) == && y < a.y;}
bool operator == (Point a) const { return sgn(x - a.x) == && sgn(y - a.y) == ;}
Point operator + (Point a) { return Point(x + a.x, y + a.y);}
Point operator - (Point a) { return Point(x - a.x, y - a.y);}
Point operator * (double p) { return Point(x * p, y * p);}
Point operator / (double p) { return Point(x / p, y / p);}
} ; inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;}
inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;}
inline double veclen(Point x) { return sqrt(dot(x, x));}
inline Point vecunit(Point x) { return x / veclen(x);}
inline Point normal(Point x) { return Point(-x.y, x.x) / veclen(x);} const int N = ;
Point pts[N * N];
int ptcnt; struct Line {
Point s, t;
Line() {}
Line(Point s, Point t) : s(s), t(t) {}
Point vec() { return t - s;}
Point point(double p) { return s + vec() * p;}
} ; inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));}
inline bool onseg(Point x, Point a, Point b) { return sgn(cross(a - x, b - x)) == && sgn(dot(a - x, b - x)) <= ;}
inline bool onseg(Point x, Line l) { return onseg(x, l.s, l.t);} const double R = 10.0;
inline bool oncircle(Point x) { return sgn(veclen(x) - R) == ;}
inline Point getpt(double p) { return Point(cos(p) * R, sin(p) * R);}
inline double angle(Point x) { return atan2(x.y, x.x);} struct Node {
double ang;
int id;
bool arc;
Node() {}
Node(double ang, int id) : ang(ang), id(id) { arc = false;}
bool operator < (Node x) const { return sgn(ang - x.ang) < || sgn(ang - x.ang) == && arc > x.arc;}
} ;
Line cut[N]; const double PI = acos(-1.0);
template<class T> T sqr(T x) { return x * x;}
Point ori, tmp[N << ];
vector<Node> nb[N * N], oc;
typedef pair<int, int> PII;
typedef pair<int, bool> PIB;
set<PII> used;
map<int, PIB> nx[N * N], anx[N * N]; inline double caltri(Point a, Point b) { return cross(a, b) / 2.0;}
double calsec(Point a, Point b) {
double da = atan2(b.y, b.x) - atan2(a.y, a.x);
da += da < ? PI * 2.0 : 0.0;
return sqr(R) * da / 2.0;
} int main() {
// freopen("in", "r", stdin);
// freopen("out", "w", stdout);
int T, n;
double s, t;
Point ip;
scanf("%d", &T);
while (T-- && ~scanf("%d", &n)) {
ptcnt = ;
used.clear();
for (int i = ; i < n; i++) {
scanf("%lf%lf", &s, &t);
cut[i] = Line(getpt(s), getpt(t));
pts[ptcnt++] = getpt(s);
pts[ptcnt++] = getpt(t);
for (int j = ; j < i; j++) {
if (sgn(cross(cut[i].vec(), cut[j].vec()))) {
ip = llint(cut[i], cut[j]);
// cout << "ip " << ip.x << ' ' << ip.y << endl;
if (onseg(ip, cut[i])) pts[ptcnt++] = ip;
}
}
}
// cout << "pt " << ptcnt << endl;
sort(pts, pts + ptcnt);
ptcnt = unique(pts, pts + ptcnt) - pts;
// cout << "npt " << ptcnt << endl;
for (int i = ; i <= ptcnt; i++) nb[pts[i - ].id = i].clear(), nx[i].clear(), anx[i].clear();
int ptn;
for (int i = ; i < n; i++) {
ptn = ;
for (int j = ; j <= ptcnt; j++) {
if (onseg(pts[j - ], cut[i])) tmp[ptn++] = pts[j - ];
}
sort(tmp, tmp + ptn);
for (int j = ; j < ptn; j++) {
nb[tmp[j].id].push_back(Node(angle(tmp[j - ] - tmp[j]), tmp[j - ].id));
nb[tmp[j - ].id].push_back(Node(angle(tmp[j] - tmp[j - ]), tmp[j].id));
}
}
oc.clear();
for (int i = ; i <= ptcnt; i++) if (oncircle(pts[i - ])) oc.push_back(Node(angle(pts[i - ]), i));
sort(oc.begin(), oc.end());
// for (int i = 0; i < oc.size(); i++) cout << oc[i].id << ' '; cout << endl;
oc.push_back(oc[]);
for (int i = , sz = oc.size(); i < sz; i++) {
nb[oc[i].id].push_back(Node(angle(pts[oc[i - ].id - ] - pts[oc[i].id - ]), oc[i - ].id));
nb[oc[i].id][nb[oc[i].id].size() - ].arc = true;
nb[oc[i - ].id].push_back(Node(angle(pts[oc[i].id - ] - pts[oc[i - ].id - ]), -oc[i].id));
nb[oc[i - ].id][nb[oc[i - ].id].size() - ].arc = true;
}
for (int i = ; i <= ptcnt; i++) {
sort(nb[i].begin(), nb[i].end());
// cout << i << " : " << pts[i - 1].x << ' ' << pts[i - 1].y << endl;
nb[i].push_back(nb[i][]);
// for (int j = 0; j < nb[i].size(); j++) cout << nb[i][j].id << '-' << nb[i][j].arc << ' '; cout << endl;
for (int j = , sz = nb[i].size(); j < sz; j++) {
if (nb[i][j].id < ) continue;
if (nb[i][j].arc) {
if (nb[i][j - ].arc) { if (j < nb[i].size() - ) nx[nb[i][j + ].id][i] = PIB(abs(nb[i][j - ].id), true), j++; else nx[nb[i][].id][i] = PIB(abs(nb[i][j - ].id), true);}
else anx[nb[i][j].id][i] = PIB(abs(nb[i][j - ].id), false);
} else {
if (!nb[i][j - ].arc || nb[i][j - ].id < ) nx[nb[i][j].id][i] = PIB(abs(nb[i][j - ].id), nb[i][j - ].arc);
}
}
nb[i].pop_back();
}
// for (int i = 1; i <= ptcnt; i++) {
// if (anx[i].size()) cout << anx[i].size() << '~' << (*anx[i].begin()).first << '~' << (*anx[i].begin()).second.first << ' ' << nx[i].size() << endl;
// else puts("~~~");
// }
double mx = 0.0, area;
int ls, cur;
PIB tt;
bool arc;
for (int i = ; i < ptcnt; i++) {
for (int j = , sz = nb[i].size(); j < sz; j++) {
if (nb[i][j].arc) continue;
ls = i, cur = nb[i][j].id;
if (used.find(PII(ls, cur)) != used.end()) continue;
arc = false;
area = caltri(pts[ls - ], pts[cur - ]);
used.insert(PII(ls, cur));
// cout << "start " << ls << ' ';
int cnt = ;
while (cur != i && cnt--) {
// cout << cur << ' ';
if (arc) tt = anx[ls][cur];
else tt = nx[ls][cur];
ls = cur, cur = tt.first, arc = tt.second;
if (arc) area += calsec(pts[ls - ], pts[cur - ]);
else area += caltri(pts[ls - ], pts[cur - ]), used.insert(PII(ls, cur));
}
// cout << area << endl;
mx = max(mx, fabs(area));
}
}
printf("%.2f\n", mx);
}
return ;
}

——written by Lyon

poj 3743 LL’s cake (PSLG,Accepted)的更多相关文章

  1. POJ 3743 LL’s cake(圆+PSLG)

    题意是给你一块在原点半径为10的圆,然后告诉你一条直线在圆弧上的极角,相当于用这条直线把这个圆分成两半,然后一共是n条直线切圆,就好比切蛋糕,问你其中最大一块的面积是多少. 如果我们将圆弧转化成直线边 ...

  2. POJ 2828 Buy Tickets(排队问题,线段树应用)

    POJ 2828 Buy Tickets(排队问题,线段树应用) ACM 题目地址:POJ 2828 Buy Tickets 题意:  排队买票时候插队.  给出一些数对,分别代表某个人的想要插入的位 ...

  3. POJ 2135 Farm Tour (网络流,最小费用最大流)

    POJ 2135 Farm Tour (网络流,最小费用最大流) Description When FJ's friends visit him on the farm, he likes to sh ...

  4. POJ 2516 Minimum Cost (网络流,最小费用流)

    POJ 2516 Minimum Cost (网络流,最小费用流) Description Dearboy, a goods victualer, now comes to a big problem ...

  5. POJ 3159 Candies(差分约束,最短路)

    Candies Time Limit: 1500MS   Memory Limit: 131072K Total Submissions: 20067   Accepted: 5293 Descrip ...

  6. POJ 3259 Wormholes(最短路,判断有没有负环回路)

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 24249   Accepted: 8652 Descri ...

  7. POJ 2175 Evacuation Plan (费用流,负环,消圈法,SPFA)

    http://poj.org/problem?id=2175 Evacuation Plan Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  8. [ACM] POJ 3687 Labeling Balls (拓扑排序,反向生成端)

    Labeling Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10161   Accepted: 2810 D ...

  9. POJ 3154 Graveyard【多解,数论,贪心】

    Graveyard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1707   Accepted: 860   Specia ...

随机推荐

  1. 13类100个常用Linux基础命令

    玩过Linux的人都会知道,Linux中的命令的确是非常多,但是玩过Linux的人也从来不会因为Linux的命令如此之多而烦恼,因为我们只需要掌握我们最常用的命令就可以了.然而每个人玩Linux的目的 ...

  2. oracle-表空间-用户-角色-权限

    概要图 概要图 一 表空间 1.1创建表空间 --问题:创建一个名为hp的表空间,指定数据文件为hp.dbf,大小为10m. create tablespace hp datafile 'C:\app ...

  3. leetcode 198-234 easy

    198. House Robber 相邻不能打劫,取利益最大化. 思想:当前值和前一个和的总数   与  前一个和    做大小比较,取最大值,重复该步骤. class Solution { publ ...

  4. PHP的注释规范

    <?php //注释规范 /** *函数的功能 *@param 参数类型 参数名1 参数解析 *@param 参数类型 参数名2 参数解析 *@return 返回值类型 返回值解析 *@auth ...

  5. CSS-DOM的小知识(一)

    在DOM编程艺术中,CSS-DOM应用很广泛. 1.style属性 通过element.style.property可以获得元素的样式,但是style属性只能够返回内嵌样式,对于外部样式表的样式和he ...

  6. 使用php实现单点登录

    1.准备两个虚拟域名 127.0.0.1  www.openpoor.com 127.0.0.1  www.myspace.com 2.在openpoor的根目录下创建以下文件 index.PHP [ ...

  7. 从零起步 系统入门Python爬虫工程师

    从零起步 系统入门Python爬虫工程师 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单论单个知识点课程本身没问题,大家看的 ...

  8. Katalon系列十八:用例变量&用例间调用

    一.用例变量写用例时,我们可以用代码定义变量,如:String name = '新闻'println(name) 上面是硬编码,我们也可以在用例里定义变量,只在该用例里生效哦,想跨用例就用全局变量. ...

  9. HTML5拖放API实现拖放排序的实例代码

    想要拖放某个元素,必须设置该元素的 draggable 属性为 true,当该属性为 false 时,将不允许拖放.而 img 元素和 a 元素都默认设置了 draggable 属性为 true,可直 ...

  10. 51nod1196 字符串的数量

    用N个不同的字符(编号1 - N),组成一个字符串,有如下要求:(1) 对于编号为i的字符,如果2 * i > n,则该字符可以作为结尾字符.如果不作为结尾字符而是中间的字符,则该字符后面可以接 ...