思路:刚开始没看懂题意,其实和求多边形的核类似,这是求半平面的交。开始我感觉用复数表示点,很不习惯,以前从没用过。
poing a; 然后这样给a赋值a.imag() = 0;用C++提交时就一直CE,然后问冰哥,他说在他的DEV c++上有警告,然后我就改为初始化成员列表
然后就AC啦,还是挺兴奋的!
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const double eps = 1e-10;
const double maxn = 20100;
typedef complex point;
//2451 Accepted 3344K 704MS C++ 3383B 2013-06-04 19:03:55
typedef pair halfplane;
vector term(maxn*4);//全局变量保存开始的半平面。
point operator + (const point &a, const point b) {
return point(a.real()+b.real(), a.imag()+b.imag());
}
point operator - (const point &a, const point b) {
return point(a.real()-b.real(), a.imag()-b.imag());
}
inline int sgn(double n) {
return fabs(n)< eps ? 0 : (n<0 ? -1 : 1);
}
inline double cross(point a, point b) {
return (conj(a)*b).imag();
}
inline double dot(point a, point b) {
return (conj(a)*b).real();
}
//点a在半平面的左侧或在半平面上。
inline double satisfy(point a, halfplane p) {
return sgn(cross(a-p.first, p.second-p.first))<=0;
}
//求半平面交点.
point crosspoint(const halfplane &a, const halfplane &b) {
double k = cross(b.first-b.second, a.first-b.second);
k = k / (k-cross(b.first-b.second, a.second-b.second));
return a.first + (a.second - a.first)*k;
}
//对给出的半平面排序,arg的范围(-PI, PI] 弧度表示。
bool cmp(const halfplane &a, const halfplane &b) {
int res = sgn(arg(a.second-a.first) - arg(b.second - b.first));
return res == 0 ? satisfy(a.first, b) : res < 0;
}
vector halfplane_intersection(vector v) {
sort(v.begin(), v.end(), cmp);
deque q;
deque ans;
q.clear();
ans.clear();
q.push_back(v[0]);
for(int i = 1; i < int(v.size()); i++) {
if(sgn(arg(v[i].second - v[i].first) - arg(v[i-1].second-v[i-1].first))==0)
continue;
while(ans.size()>0 && !satisfy(ans.back(), v[i])) {
ans.pop_back();
q.pop_back();
}
while(ans.size()>0 && !satisfy(ans.front(), v[i])) {
ans.pop_front();
q.pop_front();
}
ans.push_back(crosspoint(q.back(), v[i]));
q.push_back(v[i]);
}
while(ans.size()>0 && !satisfy(ans.back(), q.front())) {
ans.pop_back();
q.pop_back();
}
while(ans.size()>0 && !satisfy(ans.front(), q.back())) {
ans.pop_front();
q.pop_back();
}
ans.push_back(crosspoint(q.back(), q.front()));
return vector(ans.begin(), ans.end());
}
//求多边形面积。
double get_area(vector v) {
int Size = v.size();
double area = 0;
for(int i = 1; i < Size-1; i++) {
area += cross(v[i]-v[0], v[i+1]-v[0]);
}
return area/2;
}
//用成员初始化来初始化平面
void init() {
term.clear();
point a(0,0), b(10000, 0), c(10000, 10000), d(0, 10000);
term.push_back(halfplane(a, b));
term.push_back(halfplane(b, c));
term.push_back(halfplane(c, d));
term.push_back(halfplane(d, a));
}
int main()
{
int n;
double a, b, c, d; //how many halfplane;
while(scanf("%d", &n) != EOF) {
init();
for(int i = 0; i < n; i++) {
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
halfplane tmp(point(a,b), point(c,d));//初始化
term.push_back(tmp);
}
/*
这样就一顿CE.
for(int i = 0; i < n; i++) {
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
tmp.first.real() = a;
tmp.first.imag() = b;
tmp.second.real() = c;
tmp.second.imag() = d;
term.push_back(tmp);
}
*/
vector result = halfplane_intersection(term);
double res = get_area(result);
printf("%.1lf\n", res);
result.clear();
}
return 0;
}
/**
input:
3
10000 10000 0 5000
10000 5000 5000 10000
0 5000 5000 0
7
1 1 5 1
5 1 5 4
5 4 1 6
1 6 1 1
1 2 2 1
5 4 1 4
5 4 1 2
output:
54166666.7
7.5
**/