题意:有很多国家,国家的边界是包括房子和发电站的凸包,当发动战争是,会用飞毛腿导弹摧毁对方的发电站,则这个国家就会灭亡,给出每个国家的点的集合,包括房子和发电站,给出炮弹可以打中的点,计算出被摧毁的国家的总面积。
解题:计算出每个国家的凸包,如果没打中了就计算面积,然后求和。即使被打中很多次的话,面积只能算一次的。
WA:cmp中,为了防止超,就用了long long ,但是在计算时类型转化出错,等号右边没有强制转化,但是其实用int就可以过,没必要用大类型就不要用。
代码:
//uva109 SCUD Busters
//AC By Warteac
//Runtime:0.015s
//2013-5-14
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include <iomanip>
#include<algorithm>
#include<cmath>
using namespace std;
typedef int PType;//定义点的类型
///
struct point{
PType x,y;
point(PType a = 0, PType b = 0){x = a; y = b;}
void transfer(point p){x -= p.x, y -= p.y;}
void restore(point p){x += p.x, y += p.y;}
void print(){cout << "x = " << x << "y = " << y << endl;}
};
int direction(point v1,point v2){
return (v1.x*v2.y-v1.y*v2.x);
}
bool cmp(point p1, point p2){
long long cosx1 = (long long)p1.x*p1.x*(p2.x*p2.x+p2.y*p2.y); //等号右边一定要加long long,否则没有效果
long long cosx2 = (long long)p2.x*p2.x*(p1.x*p1.x+p1.y*p1.y);
if(p1.x < 0) cosx1 *=(-1);
if(p2.x < 0) cosx2 *=(-1);
return cosx1 < cosx2;
}
/*
经过简化的cmp,避免了数据范围过大的问题
bool cmp(point p1,point p2){
return (p1.x*p2.y < p1.y*p2.x);
}
*/
bool grham_scan(vector <point> p , vector <point> &parray){
//find first point p0 with minimum y-coordinate or minimun x-coordinate if y are the same
PType x = p[0].x, y = p[0].y;
int index = 0,i;
for(i = 1; i < p.size(); i++){
if(p[i].y > y) continue;
if(p[i].y < y){
y = p[i].y; x = p[i].x; index = i;
}else if(p[i].x < x){
y = p[i].y; x = p[i].x; index = i;
}
}
point t = p[index];
p[index] = p[0];
p[0] = t;
//transfer points by p0
for(int j = 0; j < p.size(); j++){
p[j].transfer(t);
}
//let (p1,p2……pm) sorted by polar angle
sort(p.begin()+1,p.end(),cmp);
//delete those points with the same polar angle but the farthest ont from p0
vector <point> ps;//saved in ps
ps.clear();
ps.push_back(p[0]);
ps.push_back(p[1]);
for(int i = 2; i < p.size(); i++){
if(cmp(ps.back(),p[i])){
ps.push_back(p[i]);
}else if(ps.back().x < p[i].x){
ps.back() = p[i];
}
}
if(ps.size() <= 2) return false;
//get the convex hull from ps
parray.clear();
parray.push_back(ps[0]);
parray.push_back(ps[1]);
ps.push_back(ps[0]);
for(int i = 2; i < ps.size(); i++){
point v1 (ps[i].x - parray.back().x, ps[i].y - parray.back().y);
point v2 (parray.back().x - (parray.end()-2)->x, parray.back().y - (parray.end()-2)->y);
int d = direction(v2,v1);
if(d <= 0) {parray.push_back(ps[i]);}
else if(d > 0){
parray.pop_back();i--;
}
}
//restore the points' coordinate
for(int j = 0; j < parray.size(); j++){
parray[j].restore(t);
}
return true;
}
int areaOfPolygon(vector <point> &vecCH) {
int nArea = 0;
for (vector <point>::iterator i = vecCH.begin(); i != vecCH.end() - 1; ++i) {
nArea += (i + 1)->x * i->y - i->x * (i + 1)->y;
}
return nArea;
}
bool inPolygon(point pt, vector <point> &vecCH) {
for (vector <point>::iterator i = vecCH.begin(); i != vecCH.end() - 1; ++i) {
int nX1 = pt.x - i->x, nY1 = pt.y - i->y;
int nX2 = (i + 1)->x - i->x, nY2 = (i + 1)->y - i->y;
if (nX1 * nY2 - nY1 * nX2 < 0) {
return false;
}
}
return true;
}
//
int main(){
int sites;
PType x,y;
vector <point> v;
point t,mi;
vector < vector <point> > p;//convex hull
int aflag[105] = {0};
int area = 0;
//input kingdom
while(cin >> sites && sites != -1){
v.clear();
vector <point> temp;//one convex hull
while(sites--){
cin >> t.x >> t.y;
v.push_back(t);
}
//computing convex hull
if(grham_scan(v,temp) == true){
p.push_back(temp);//all convex hull
}
}
//input missile landings
while(cin >> mi.x >> mi.y){
for(int j = 0; j < p.size(); j++){
if((inPolygon(mi,p[j]) == true) && aflag[j] != 1){
aflag[j] = 1;
area += areaOfPolygon(p[j]);
break;
}
}
}
cout << setiosflags(ios::fixed) << setprecision(2);
cout << (double)area/2.0 << endl;
return 0;
}