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. jS生成二叉树,二叉树的遍历,查找以及插入

    js递归,二叉树的操作 //递归算法n次幂 function foo(n) { if (n == 1) { return 1; } else { return n * foo(n - 1); } } ...

  2. 使用Cmder 安装 Composer 出现 "attempt to call a nil value"

    原因: 不是这个原因,也不是那个原因,而是采用了中文路径, 把comder 整个搬到其他目录就行了

  3. web前端学习(四)JavaScript学习笔记部分(2)-- JavaScript语法详解

    2.1.Javascript语法-运算符(1) 复数运算符 %取余 ++ -- 赋值运算符 += -= *= /= %= 字符串操作 <!DOCTYPE html> <html la ...

  4. Codeforces Round #395 (Div. 2) A. Taymyr is calling you【数论/最小公倍数】

    A. Taymyr is calling you time limit per test 1 second memory limit per test 256 megabytes input stan ...

  5. 项目ITP(七) javaWeb 整合 Quartz 实现动态调度 而且 持久化

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u010378410/article/details/36255511 项目ITP(七) javaWe ...

  6. cnn.py cs231n

    n import numpy as np from cs231n.layers import * from cs231n.fast_layers import * from cs231n.layer_ ...

  7. golang数据运算符

     

  8. 盘点Apache毕业的11个顶级项目

    自1999年成立至今,Apache 软件基金会已成功建立起自己强大的生态圈.其社区涌现了非常多优秀的开源项目,同时有越来越多国内外项目走向这个国际开源社区进行孵化.据悉,目前所有的 Apache 项目 ...

  9. vue-cnodejs

    感谢那些无私开源的程序员,你们是最可爱的人儿~~~~ //根app app.js <template> <div id="app"> <v-heade ...

  10. parkingLot

    一个支付宝停车支付生活号前端页面 //index.html //自定义键盘 <!DOCTYPE html> <html> <head> <meta chars ...