【kuangbin专题】计算几何基础
1.poj2318 TOYS
传送:http://poj.org/problem?id=2318
题意:有m个点落在n+1个区域内。问落在每个区域的个数。
分析:二分查找落在哪个区域内。叉积判断点与线段的位置。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct point{
int x,y;
point(){ }
point(int _x,int _y):x(_x),y(_y){}
point operator +(const point &b) const{
return point(x+b.x,y+b.y);
}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
int operator *(const point &b) const{
return x*b.x,y*b.y;
}
int operator ^(const point &b) const{
return x*b.y-y*b.x;
}
};
struct line{
point s,e;
line(){}
line(point _s,point _e):s(_s),e(_e){}
}box[maxn];
int xmult(point p,point a,point b){
return (b-a)^(p-a);
}
int ans[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie();cout.tie();
int n,m,x1,y1,x2,y2,ui,li,x,y;
int _=;
while (cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n){
if (_!=) cout << endl;
for (int i=;i<n;i++){
cin >> ui >> li;
box[i]=line(point(ui,y1),point(li,y2));
}
box[n]=line(point(x2,y1),point(x2,y2));
memset(ans,,sizeof(ans));
point p;
for (int i=;i<m;i++){
cin >> x >> y;
p=point(x,y);
int l=,r=n,mid,tmp;
while (l<=r){
mid=(l+r)>>;
if (xmult(p,box[mid].s,box[mid].e)<){
tmp=mid;
r=mid-;
}
else l=mid+;
}
ans[tmp]++;
}
for (int i=;i<=n;i++) cout << i << ": " << ans[i] << endl;
_++;
}
return ;
}
poj2318
2.poj2398 Toy Storage
传送:http://poj.org/problem?id=2398
题意:与poj2318相同,输出要求输出有t(t>0)个玩具的格子数。
分析:同2318
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=;
struct point{
int x,y;
point(){ }
point(int _x,int _y):x(_x),y(_y){}
point operator +(const point &b) const{
return point(x+b.x,y+b.y);
}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
int operator *(const point &b) const{
return x*b.x,y*b.y;
}
int operator ^(const point &b) const{
return x*b.y-y*b.x;
}
};
struct line{
point s,e;
line(){}
line(point _s,point _e):s(_s),e(_e){}
//
bool operator< (const line &b) const{
return s.x<b.s.x;
} }box[maxn];
int cmp(line p,line q){
return p.s.x<q.s.x;
}
int xmult(point p,point a,point b){
return (a-p)^(b-p);
}
int ans[maxn],vis[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie();cout.tie();
int n,m,x1,y1,x2,y2,ui,li,x,y;
while (cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n){
for (int i=;i<n;i++){
cin >> ui >> li;
box[i]=line(point(ui,y1),point(li,y2));
}
box[n]=line(point(x2,y1),point(x2,y2));
sort(box,box++n);
memset(ans,,sizeof(ans));
point p;
for (int i=;i<m;i++){
cin >> x >> y;
p=point(x,y);
int l=,r=n,mid,tmp;
while (l<=r){
mid=(l+r)>>;
if (xmult(p,box[mid].s,box[mid].e)<){
tmp=mid;
r=mid-;
}
else l=mid+;
}
ans[tmp]++;
}
memset(vis,,sizeof(vis));
for (int i=;i<=n;i++) if (ans[i]) vis[ans[i]]++;
cout << "Box\n";
for (int i=;i<=n;i++){
if (!vis[i]) continue;
cout << i << ": " << vis[i] << endl;
}
}
return ;
}
poj2398
3.poj3304 Segments
传送:http://poj.org/problem?id=3304
题意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。
分析:如果有存在这样的直线,过投影相交区域作直线的垂线,该垂线必定与每条线段相交,问题转化为问是否存在一条线和所有线段相交。
直线肯定经过两个端点。两两枚举端点(包括同一条线段),判断直线和线段是否相交。
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps=1e-;
const int maxn=;
struct point{
double x,y;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b) const{
return x*b.y-y*b.x;
}
double operator *(const point &b) const{
return x*b.x+y*b.y;
}
};
struct line{
point s,t;
line(){}
line(point _s,point _t):s(_s),t(_t){}
}a[maxn];
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
double xmult(point p,point a,point b){ // PA X PB
return (a-p)^(b-p);
}
int seg_inter_line(line l1,line l2){
return sgn(xmult(l2.s,l1.s,l1.t))*sgn(xmult(l2.t,l1.s,l1.t))<=;
}
double dist(point a,point b){
return sqrt((b-a)*(b-a));
}
int check(line l1,int n){
if (sgn(dist(l1.s,l1.t))==) return ;
for (int i=;i<n;i++)
if (seg_inter_line(l1,a[i])==) return ;
return ;
}
int main(){
int t,n; cin >> t;
double x1,x2,y1,y2;
while (t--){
cin >> n;
for (int i=;i<n;i++){
cin >> x1 >> y1 >> x2 >> y2;
a[i]=line(point(x1,y1),point(x2,y2));
}
int f=;
for (int i=;i<n;i++){
for (int j=;j<n;j++){
if (check(line(a[i].s,a[j].s),n) || check(line(a[i].s,a[j].t),n)
|| check(line(a[i].t,a[j].s),n) || check(line(a[i].t,a[j].t),n)){
f=; break;
}
}
}
if (f) cout << "Yes!\n";
else cout << "No!\n";
}
}
poj3304
4.poj1269 Intersecting Lines
传送:http://poj.org/problem?id=1269
题意:给出两条直线,问两条直线的位置关系(平行,重合,相交)。相交的话输出交点。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const double eps=1e-;
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
struct point{
double x,y;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b) const{
return x*b.y-y*b.x;
}
double operator *(const point &b) const{
return x*b.x+y*b.y;
}
};
struct line{
point s,t;
line(){}
line(point _s,point _t):s(_s),t(_t){}
pair<point,int> operator &(const line &b) const{
point res=s;
if (sgn((s-t)^(b.s-b.t))==){
if (sgn((b.s-s)^(b.t-s))==) return make_pair(res,); //两直线重合
else return make_pair(res,); //两直线平行
}
double k=((s-b.s)^(b.s-b.t))/((s-t)^(b.s-b.t));
res.x+=(t.x-s.x)*k;
res.y+=(t.y-s.y)*k;
return make_pair(res,); //两直线相交
}
};
int main(){
int n; cin >> n;
double x1,x2,y1,y2;
line l1,l2;
cout << "INTERSECTING LINES OUTPUT\n";
for (int i=;i<n;i++){
cin >> x1 >> y1 >> x2 >> y2;
l1=line(point(x1,y1),point(x2,y2));
cin >> x1 >> y1 >> x2 >> y2;
l2=line(point(x1,y1),point(x2,y2));
pair<point,int> ans=l1&l2;
if (ans.second==) printf("POINT %.2f %.2f\n",ans.first.x,ans.first.y);
else if (ans.second==) printf("NONE\n");
else printf("LINE\n");
}
cout << "END OF OUTPUT\n";
return ;
}
poj1269
5.poj1556 The Doors
传送:http://poj.org/problem?id=1556
题意:10×10的方阵内有若干个墙壁,墙壁之间有空隙(可通过),问从(0,5)到(10,5)的最短路。
分析:建图,线段两两判断是否相交,不相交就建边。然后跑最短路。(数据较小,随便最短路算法。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps=1e-;
const double inf=1e20;
const int maxn=;
double mp[maxn][maxn];
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
struct point{
double x,y;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b) const{
return x*b.y-y*b.x;
}
double operator *(const point &b) const{
return x*b.x+y*b.y;
}
};
struct line{
point s,e;
line(){}
line(point _s,point _e):s(_s),e(_e){}
}a[maxn];
double dist(point a,point b){
return sqrt((b-a)*(b-a));
}
int inter(line l1,line l2){
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
&& max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
&& max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
&& max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
&& sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
&& sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
}
double floyd(int n){
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
for (int k=;k<=n;k++)
if (mp[i][k]+mp[k][j]<mp[i][j]) mp[i][j]=mp[i][k]+mp[k][j];
return mp[][n];
}
int main(){
int n; double x,y1,y2,y3,y4;
while (cin >> n && n!=-){
for (int i=;i<=n;i++){
cin >> x >> y1 >> y2 >> y3 >> y4;
a[*i-]=line(point(x,y1),point(x,y2));
a[*i]=line(point(x,y3),point(x,y4));
}
for (int i=;i<=*n+;i++)
for (int j=;j<=*n+;j++)
if (i==j) mp[i][j]=;else mp[i][j]=inf;
for (int i=;i<=*n;i++){
int l=(i+)/;
int f=;
point tmp;
if (i&) tmp=a[(i+)/].s; else tmp=a[(i+)/].e;
for (int j=;j<l;j++)
if (inter(a[*j-],line(point(,),tmp))==
&& inter(a[*j],line(point(,),tmp))==) f=;
if (f) mp[][i]=mp[i][]=dist(point(,),tmp);
f=;
for (int j=l+;j<=n;j++)
if (inter(a[*j-],line(point(,),tmp))==
&& inter(a[*j],line(point(,),tmp))==) f=;
if (f) mp[i][*n+]=mp[*n+][i]=dist(point(,),tmp);
}
for (int i=;i<=*n;i++){
for (int j=i+;j<=*n;j++){
int l1=(i+)/,l2=(j+)/;
int f=;
point p1,p2;
if (i&) p1=a[(i+)/].s; else p1=a[(i+)/].e;
if (j&) p2=a[(j+)/].s; else p2=a[(j+)/].e;
for (int k=l1+;k<l2;k++)
if (inter(a[*k-],line(p1,p2))==
&& inter(a[*k],line(p1,p2))==) f=;
if (f) mp[i][j]=mp[j][i]=dist(p1,p2);
}
}
int f=;
for (int i=;i<=n;i++)
if (inter(a[*i-],line(point(,),point(,)))==
&& inter(a[*i],line(point(,),point(,)))==) f=;
if (f) mp[][*n+]=mp[*n+][]=;
double ans=floyd(*n+);
printf("%.2f\n",ans);
}
return ;
}
poj1556
6.poj2653 Pick-up sticks
传送:http://poj.org/problem?id=2653
题意:问有多少线段不与比它编号大的相交。
分析:线段交直接暴力判断。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-;
const int maxn=;
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
struct point{
double x,y;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b) const{
return x*b.y-y*b.x;
}
double operator *(const point &b) const{
return x*b.x+y*b.y;
}
};
struct line{
point s,e;
line(){}
line(point _s,point _e):s(_s),e(_e){}
}a[maxn];
double dist(point a,point b){
return sqrt((b-a)*(b-a));
}
int inter(line l1,line l2){
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
&& max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
&& max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
&& max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
&& sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
&& sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
}
bool vis[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie();cout.tie();
int n; double x1,x2,y1,y2;
while (cin >> n && n){
for (int i=;i<n;i++){
cin >> x1 >> y1 >> x2 >> y2;
a[i]=line(point(x1,y1),point(x2,y2));
vis[i]=;
}
for (int i=;i<n;i++){
for (int j=i+;j<n;j++){
if (inter(a[i],a[j])){vis[i]=;break;}
}
}
cout << "Top sticks: ";
int f=;
for (int i=;i<n;i++){
if (!vis[i]) continue;
if (f){cout << i+;f=;}
else cout << ", " << i+;
}
cout << ".\n";
}
}
poj2653
7.poj1066 Treasure Hunt
传送:http://poj.org/problem?id=1066
题意:在金字塔内有一个宝藏p(x,y);现在要取出这个宝藏在金字塔内有许多墙为了进入宝藏所在的房间必须把墙炸开但是炸墙只能炸每个房间墙的中点求将宝藏运出城堡所需要的最小炸墙数。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const double dx[]={,,,},dy[]={,,,};
const double eps=1e-;
const int maxn=;
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
struct point{
double x,y;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b) const{
return x*b.y-y*b.x;
}
double operator *(const point &b) const{
return x*b.x+y*b.y;
}
}p[*maxn];
struct line{
point s,e;
line(){}
line(point _s,point _e):s(_s),e(_e){}
}a[maxn];
int inter(line l1,line l2){
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
&& max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
&& max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
&& max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
&& sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
&& sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
}
int main(){
int n; double x1,y1,x2,y2;
while (cin >> n){
for (int i=;i<=n;i++){
cin >> x1 >> y1 >> x2 >> y2;
a[i]=line(point(x1,y1),point(x2,y2));
p[*i-]=point(x1,y1); p[*i]=point(x2,y2);
}
point s;
cin >> x1 >> y1;
s=point(x1,y1);
int ans=;
for (int i=;i<=*n;i++){
line l1=line(s,p[i]);
int res=;
for (int j=;j<=n;j++)
if (inter(l1,a[j])) res++;
ans=min(res,ans);
}
for (int i=;i<;i++){
line l1=line(s,point(dx[i],dy[i]));
int res=;
for (int j=;j<=n;j++)
if (inter(l1,a[j])) res++;
ans=min(ans,res+);
}
cout << "Number of doors = " << ans << endl;
}
return ;
}
poj1066
8.poj1410 Intersection
传送:http://poj.org/problem?id=1410
题意:给定一个矩阵和线段,若线段在矩阵内或与矩阵某条边相交,输出T,否则输出F。
分析:判断线段与四条边线段交。再判断是否在矩阵内。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps=1e-;
const int maxn=;
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
struct point{
double x,y;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b) const{
return x*b.y-y*b.x;
}
double operator *(const point &b) const{
return x*b.x+y*b.y;
}
}p[maxn];
struct line{
point s,e;
line(){}
line(point _s,point _e):s(_s),e(_e){}
};
int inter(line l1,line l2){
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x)
&& max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x)
&& max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y)
&& max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y)
&& sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=
&& sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=;
}
int onseg(point p,line l){
return
sgn((l.s-p)^(l.e-p))== &&
sgn((p.x-l.s.x)*(p.x-l.e.x))<= &&
sgn((p.y-l.s.y)*(p.y-l.e.y))<=;
}
//判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(point a,point p[],int n){
for (int i=;i<n;i++){
if (sgn((p[i]-a)^(p[(i+)%n]-a))<) return -;
else if (onseg(a,line(p[i],p[(i+)%n]))) return ;
}
return ;
}
int main(){
int t; cin >> t;
double x1,y1,x2,y2;
while (t--){
cin >> x1 >> y1 >> x2 >> y2;
line l=line(point (x1,y1),point(x2,y2));
cin >> x1 >> y1 >> x2 >> y2;
if (x1>x2) swap(x1,x2); if (y1>y2) swap(y1,y2);
p[]=point(x1,y1);p[]=point(x2,y1);p[]=point(x2,y2);p[]=point(x1,y2);
if (inter(l,line(p[],p[])) || inter(l,line(p[],p[]))
|| inter(l,line(p[],p[])) || inter(l,line(p[],p[]))){
cout << "T\n";continue;
}
if (inConvexPoly(l.s,p,)>= || inConvexPoly(l.e,p,)>=){
cout << "T\n"; continue;
}
cout << "F\n";
}
return ;
}
poj1410
9.poj1696 Space Ant
传送:http://poj.org/problem?id=1696
题意:一只蚂蚁只会向左转,现在给出平面上很多个点,求解一种走法能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉。
分析:对于题目所输入的点,先找出最左下方的顶点(即纵坐标最小的顶点),然后对剩下的顶点按照对与左下点的极角排序,然后反复找最左下的点,反复进行极角排序,同时记录排序后左下的顶点。
极角排序方法:利用叉积,看向量p1和p2的叉积是否小于零,是则说明p1在p2逆时针方向,即p1的极角比p2的大,极角相同则按离p0距离降序排序。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-;
const int maxn=;
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
struct point{
double x,y;
int id;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator -(const point &b) const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b) const{
return x*b.y-y*b.x;
}
double operator *(const point &b) const{
return x*b.x+y*b.y;
}
}p[maxn];
double dist(point a,point b){
return sqrt((a-b)*(a-b));
}
int pos;
int cmp(point a,point b){
double tmp=(a-p[pos])^(b-p[pos]);
if (sgn(tmp)==) return dist(a,p[pos])<dist(b,p[pos]);
else if (sgn(tmp)<) return false;
else return true;
}
int main(){
int t,n; cin >> t;
double x,y;
while (t--){
cin >> n;
for (int i=;i<n;i++){
cin >> p[i].id >> p[i].x >> p[i].y;
if (p[i].y<p[].y || p[i].y==p[].y && p[i].x<p[].x) swap(p[i],p[]);
}
pos=;
for (int i=;i<n;i++){
sort(p+i,p+n,cmp);
pos++;
}
cout << n;
for (int i=;i<n;i++) cout << " " << p[i].id;
cout << endl;
}
}
poj1696
10.poj3347 Kadj Squares
传送:http://poj.org/problem?id=3347
题意:给出n个边长的正方形,要求尽可能贴着放。问最后从上往下看能看到哪几个正方形。
分析:每新增一个正方形,就让他与左侧的每一个正方形贴紧,求的其左端坐标,最终结果一定是最大的那个。然后求的相应的最右端坐标。这样就转化为了线段,最后用朴素的n2算法求出每条线段没有被覆盖的长度,如果长度大于0,即可输出。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=;
struct node{
int len,l,r;
}a[maxn];
int main(){
int n;
while (cin >> n && n){
for (int i=;i<n;i++){
cin >> a[i].len; //将图形扩大根2倍,len为对角线长度的一半
a[i].l=;
for (int j=;j<i;j++){
a[i].l=max(a[i].l,a[j].r-abs(a[i].len-a[j].len));
}
a[i].r=a[i].l+*a[i].len;
}
for (int i=;i<n;i++){
for (int j=;j<i;j++){
if (a[i].l<a[i].r){
if (a[i].len<a[j].len && a[i].l<a[j].r) a[i].l=a[j].r;
else if (a[i].len>a[j].len && a[i].l<a[j].r) a[j].r=a[i].l;
}
}
}
for (int i=;i<n;i++){
if (a[i].l<a[i].r) cout << i+ << " ";
}
cout << endl;
}
return ;
}
poj3347
11.poj1654 Area
传送:http://poj.org/problem?id=1654
题意:从原点开始,超八个方向走。问最后形成的多边形面积。
分析:rt。直接求多边形面积。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int dx[]={,-,,,-,,,-,,},dy[]={,-,-,-,,,,,,};
const int maxn=;
typedef long long ll;
struct point{
int x,y;
point(){}
point(int _x,int _y):x(_x),y(_y){}
ll operator ^(const point &b)const{
return x*b.y-y*b.x;
}
};
struct polygon{
int n;
point p[maxn];
void add(point q){p[n++]=q;}
ll getarea(){
ll sum=;
for (int i=;i<n;i++) sum+=(p[i]^(p[(i+)%n]));
return sum<?-sum:sum;
}
};
polygon C;
int main(){
char ch;
int t,k; cin >> t;
while (t--){
C.n=;
ll x=,y=;
while (cin >> ch && ch!=''){
k=ch-'';
x+=dx[k]; y+=dy[k];
C.add(point(x,y));
}
ll ans=C.getarea();
if (ans&) cout << ans/ << ".5\n";
else cout << ans/ << endl;
}
return ;
}
poj1654
12.poj2954 Triangle
传送:http://poj.org/problem?id=2954
题意:求三角形内部有多少格点。
分析:pick定理。S=a+b/2-1。a代表多边形内部的格点,b代表多边形边上的格点。S代表多边形面积。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn=;
struct point{
int x,y;
point(){}
point(int _x,int _y):x(_x),y(_y){}
ll operator ^(const point &b)const{
return x*b.y-y*b.x;
}
};
struct polygon{
int n;
point p[maxn];
void add(point q){p[n++]=q;}
ll getarea(){
ll sum=;
for (int i=;i<n;i++) sum+=(p[i]^p[(i+)%n]);
return sum<?-sum:sum;
}
};
polygon C;
ll gcd(ll a,ll b){
if (b==) return a;
else return gcd(b,a%b);
}
int main(){
int x1,x2,x3,y1,y2,y3;
while (cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3){
if (!x1 && !x2 && !x3 && !y1 && !y2 && !y3) break;
C.n=;
C.add(point(x1,y1));C.add(point(x2,y2));C.add(point(x3,y3));
ll area=C.getarea();
int b=;
for (int i=;i<C.n;i++){
b+=gcd(abs(C.p[i].x-C.p[(i+)%C.n].x),abs(C.p[i].y-C.p[(i+)%C.n].y));
}
cout << (area+-b)/ << endl; //S=a+b/2-1
}
return ;
}
poj2954
【kuangbin专题】计算几何基础的更多相关文章
- [kuangbin]专题六 最小生成树 题解+总结
kuangbin专题链接:https://vjudge.net/article/752 kuangbin专题十二 基础DP1 题解+总结:https://www.cnblogs.com/RioTian ...
- nyis oj 68 三点顺序 (计算几何基础)
三点顺序 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 如今给你不共线的三个点A,B,C的坐标,它们一定能组成一个三角形,如今让你推断A,B,C是顺时针给出的还是逆 ...
- kuangbin专题 数论基础 part1?
线段树专题太难了,那我来做数学吧! 但数学太难了,我......(扯 这两天想了做了查了整理了几道数学. 除了一些进阶的知识,像莫比乌斯反演,杜教筛,min25学不会我跳了,一些基础的思维还是可以记录 ...
- 【BZOJ】1043: [HAOI2008]下落的圆盘(计算几何基础+贪心)
http://www.lydsy.com/JudgeOnline/problem.php?id=1043 唯一让我不会的就是怎么求圆的周长并QAAQ... 然后发现好神!我们可以将圆弧变成$[0, 2 ...
- 计算几何基础——矢量和叉积 && 叉积、线段相交判断、凸包(转载)
转载自 http://blog.csdn.net/william001zs/article/details/6213485 矢量 如果一条线段的端点是有次序之分的话,那么这种线段就称为 有向线段,如果 ...
- BZOJ_1610_[Usaco2008_Feb]_Line连线游戏_(计算几何基础+暴力)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1610 给出n个点,问两两确定的直线中,斜率不同的共有多少条. 分析 暴力枚举直线,算出来斜率放 ...
- 二维计算几何基础题目泛做(SYX第一轮)
题目1: POJ 2318 TOYS 题目大意: 给一个有n个挡板的盒子,从左到右空格编号为0...n.有好多玩具,问每个玩具在哪个空格里面. 算法讨论: 直接叉积判断就可以.注意在盒子的边界上面也算 ...
- 最小生成树 kuangbin专题最后一个题
题目链接:https://cn.vjudge.net/contest/66965#problem/N 注释:这道题需要用krustra,用prim的话可能会超时.并且在计算距离的时候要尽量减少步骤,具 ...
- kuangbin专题十六 KMP&&扩展KMP HDU2087 剪花布条
一块花布条,里面有些图案,另有一块直接可用的小饰条,里面也有一些图案.对于给定的花布条和小饰条,计算一下能从花布条中尽可能剪出几块小饰条来呢? Input输入中含有一些数据,分别是成对出现的花布条和小 ...
随机推荐
- 扩展方法(深入理解c#)
1. 静态类到扩展方法: 许多方法可能都适合转为扩展方法,只要具有以下特征: 1)你想为一个类型添加一些成员: 2)你不需要为类型的实例添加更多的数据: 3)你不能改变类型本身,因为是别人的代码 2. ...
- delphi 中如何访问另一个类中到私有方法?(转载)
原始连接 http://rvelthuis.blogspot.tw/2018/01/accessing-private-methods-of-another.html Accessing privat ...
- 前端之javascript的数据类型1和BOM对象
一 js对象 BOM对象:browser object model浏览器模型对象 window对象:定时器 DOM对象:文档对象模型 js对象:字符串对象,数组对象,日期对象,math对象 new关键 ...
- 注解Demo
1.创建注解类 2.在测试实体类中使用注解 3.构建注解解析类 4.执行注解解析方法
- Linux基础笔记
基本命令: man man 查看手册 (1)pwd 显示路径 (2)cd 切换路径 (3)ls -a;-l;-h;-i;-d (隐藏的:长列表显示:human显示:索引号:只显示列表) (4)c ...
- jquery删除onclick属性和设置onclick属性--获取验证码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- shell 脚本学习
Shell简介 概述 Shell是一种具备特殊功能的程序,它提供了用户与内核进行交互操作的一种接口.它接收用户输入的命令,并把它送入内核去执行.内核是Linux系统的心脏,从开机自检就驻留在计算机的内 ...
- [HTML5] 颜色选择器的操作[input type='color'....]
一.点击事件和获取颜色值 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- Ng第十二课:支持向量机(Support Vector Machines)(三)
11 SMO优化算法(Sequential minimal optimization) SMO算法由Microsoft Research的John C. Platt在1998年提出,并成为最快的二次规 ...
- FPGA之初认识
什么是FPGA FPGA(Field-Programmable Gate Array),即现场可编程门阵列 .看到编程两个字码农就笑了,不就是编程嘛,那可是我们的强项 .且慢,此编程非彼编程 .一定要 ...