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. hive语句on和where一点小问题

    hive join 后面必须=(0.13版本后支持,不支持like,<>),on后面如需加条件语句必须放到where中不然会产生错误结果 (可以一对多,一对一,不可以多对多‘会出现数据翻倍 ...

  2. JavaScript Libraries In A TypeScript Application, Revisited

    If you haven’t already gotten involved with it, you’ll probably know that TypeScript is becoming inc ...

  3. golang在import自己的包报错问题

    原因:使用git clone项目后,项目根路径是小写英文名称,比如cmdbapi,但是项目里面的import导入自己的相关包时,红色报错 解决:把项目名称改写成import导入包的名称,即cmdbAp ...

  4. spring源码学习之默认标签的解析(一)

    继续spring源码的学习之路,现在越来越觉得这个真的很枯燥的,而且我觉得要是自己来看源码,真的看不下去,不是没有耐心,而是真的没有头绪,我觉得结合着书来看,还是很有必要的,最起码大致的流程是能够捋清 ...

  5. Django用户登陆以及跳转后台管理页面3

    Django用户登陆以及跳转后台管理页面1http://www.cnblogs.com/ujq3/p/7891774.html Django用户登陆以及跳转后台管理页面2http://www.cnbl ...

  6. Faster RCNN算法训练代码解析(1)

    这周看完faster-rcnn后,应该对其源码进行一个解析,以便后面的使用. 那首先直接先主函数出发py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py ...

  7. vim中NERDTREE插件的使用

    一个显示目录树的插件,很不错 学习于: http://blog.csdn.net/xiongzhengxiang/article/details/7375607

  8. 错觉-Info:让你难以置信的视错觉

    ylbtech-错觉-Info:让你难以置信的视错觉 1.返回顶部 1. 看下图:如果你看到舞者逆时针旋转说明你用左脑,如果看到顺时针旋转说明你用右脑思维. 据说这是耶鲁大学五年的研究成果.   下图 ...

  9. Spring使用JDBC配置具名参数

    好处:若有多个参数,则不用再去对应位置?,直接对应参数名,便于维护 缺点:较为麻烦 使用具名参数时可以使用以下的方法 好处,通过实现类BeanPropertySqlParameterSource之间传 ...

  10. HTML 5+ SDK 更新日志

    http://ask.dcloud.net.cn/article/103 离线打包 SDK App 最新Andorid平台SDK下载新版本Android SDK使用aar方式发布,部分资源和jar包整 ...