POJ 2318:
题意 : 给一个矩形,然后有n条不相交的线段,线段的两个端点在矩形的上下两条边上,这样就把矩形划分成了n+1个区域,然后给出m个点(不在线上),问最终每个区域中有几个点
思路 : 利用向量的叉乘来判断这个点在某线段的顺时针还是逆时针方向上,然后二分找到位置(线段已经排好序了)
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const double INF = 1e200;
const double EP = 1e-10;
const int maxn = 5100;
const double PI = acos(-1);
struct POINT{
int x;
int y;
POINT(int a = 0,int b = 0){x = a;y = b;}
};///点 定义
struct SEGMENT{///line segment
POINT s;
POINT e;
SEGMENT(POINT a,POINT b){s = a;e = b;}
SEGMENT(){}
};///线段 定义
struct LINE{///ax + by + c = 0&&a >= 0
double a;
double b;
double c;
LINE(double da,double db,double dc){a = da;b = db;c = dc;}
};
int multiply(POINT sp,POINT ep,POINT op){
return ((sp.x - op.x)*(ep.y - op.y) - (ep.x - op.x)*(sp.y - op.y));
}///向量op->sp X op->ep的叉乘,小于0:ep在op->sp顺时针方向//大于0:0:ep在op->sp逆时针方向//等于0:三点共线
int main(){
int n,m;
POINT pp[maxn][2];
int ans[maxn];
while(cin>>n){
if(n == 0)break;
cin>>m;
int x1,x2,y1,y2;
POINT now;
cin>>x1>>y1>>x2>>y2;
int u,l;
for(int i = 0;i < n;i ++){
cin>>u>>l;
now.x = u,now.y = y1;
pp[i][0] = now;
now.x = l,now.y = y2;
pp[i][1] = now;
}
now.x = x2;now.y = y2;
pp[n][1] = now;
now.y = y1;
pp[n++][0] = now;
//for(int i = 0;i < n;i ++)cout<<pp[i][0].x<<' '<<pp[i][0].y<<' '<<pp[i][1].x<<' '<<pp[i][1].y<<' '<<endl;
memset(ans,0,sizeof(ans));
while(m --){
int a,b;
cin>>a>>b;
now.x = a;
now.y = b;
int l = 0,r = n-1,m;
while(r - l > 0){
m = (l + r)>>1;//cout<<m<<endl;
if(multiply(pp[m][0],now,pp[m][1]) < 0)l = m+1;
else r = m;
}//cout<<endl;
ans[l] ++;
}
for(int i = 0;i < n;i ++)cout<<i<<": "<<ans[i]<<endl;//cout<<endl;
cout<<endl;
}
return 0;
}
POJ 2398:
题意:跟上一道题差不多,只不过是边没有排序,自己排一下就行了,然后输出的解不太一样
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const double INF = 1e200;
const double EP = 1e-10;
const int maxn = 5100;
const double PI = acos(-1);
struct POINT{
int x;
int y;
POINT(int a = 0,int b = 0){x = a;y = b;}
};///点 定义
struct SEGMENT{///line segment
POINT s;
POINT e;
SEGMENT(POINT a,POINT b){s = a;e = b;}
SEGMENT(){}
};///线段 定义
struct LINE{///ax + by + c = 0&&a >= 0
double a;
double b;
double c;
LINE(double da,double db,double dc){a = da;b = db;c = dc;}
};
int multiply(POINT sp,POINT ep,POINT op){
return ((sp.x - op.x)*(ep.y - op.y) - (ep.x - op.x)*(sp.y - op.y));
}///向量op->sp X op->ep的叉乘,小于0:ep在op->sp顺时针方向//大于0:0:ep在op->sp逆时针方向//等于0:三点共线
bool cmp(SEGMENT A,SEGMENT B){
return A.s.x < B.s.x;
}
int main(){
int n,m,x1,y1,x2,y2;
while(cin>>n){
if(n == 0)break;
cin>>m>>x1>>y1>>x2>>y2;
int ans[maxn];
int nn[maxn];
SEGMENT pp[maxn];
for(int i = 0;i < n;i ++){
POINT now;
int a,b;
cin>>a>>b;
now.x = a;now.y = y1;
pp[i].s = now;
now.x = b;now.y = y2;
pp[i].e = now;
}
POINT now;
now.x = x2;
now.y = y2;
pp[n].e = now;
now.y = y1;
pp[n++].s = now;
memset(ans,0,sizeof(ans));
memset(nn,0,sizeof(nn));
sort(pp,pp+n,cmp);
//for(int i = 0;i < n;i ++)cout<<pp[i].e.x <<' '<< pp[i].e.y<<endl;
while(m --){
int l = 0,r = n-1,mid;
cin>>now.x>>now.y;
while(r > l){
mid = (l + r)>>1;
if(multiply(pp[mid].s,now,pp[mid].e) < 0)l = mid +1;
else r = mid;
}
ans[l] ++;
}
cout<<"Box"<<endl;
for(int i = 0;i < n;i ++)
nn[ans[i]] ++;
for(int i = 1;i < maxn;i ++){
if(nn[i])cout<<i<<": "<<nn[i]<<endl;
}
}
return 0;
}