版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/83479695
题目链接:poj 2318
题意:给你一个盒子的俯视图,从左到右将每个格子划分为0,1,2...n;给你一些点的坐标,让你输出每个格子里点的个数。
题解见代码:
///向量P和向量Q ,假如P*Q>0 ,P在Q的顺时针方向
///p*Q<0,P在Q的逆时针方向上,
///点a在线段bc的左边,则它们的叉积小于0,点a在线段bc的右边,则它们的叉积大于0,
///https://blog.csdn.net/wangzhen_yu/article/details/44177449
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
struct point{
double x,y;
point(double x=0,double y=0):x(x),y(y){ }
};
struct line{
point S;
point E;
}card[5050];
point operator + (point a,point b) {return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);}
point operator * (point a,double p) { return point(a.x*p,a.y*p);}
point operator / (point a,double p){ return point(a.x/p,a.y/p);}
bool operator < (const point &a,const point &b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
const double esp=1e-10;
int dcmp(double x){
if(fabs(x)<esp) return 0;
else return x<0?-1:1;
}
bool operator ==(const point &a,point &b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Cross(point a,point b){ return a.x*b.y-a.y*b.x;}
double area2(point a,point b,point c){ return Cross(b-a,c-a);}
int sum[5050];
int main()
{
int n,m;
double x1,y1,x2,y2;
while(scanf("%d",&n)&&n)
{
scanf("%d%lf%lf%lf%lf",&m,&x1,&y1,&x2,&y2);
card[0].S.x=x1;
card[0].S.y=y1;
card[0].E.x=x1;
card[0].E.y=y2;
card[n+1].S.x=x2;
card[n+1].S.y=y1;
card[n+1].E.x=x2;
card[n+1].E.y=y2;
double l,r;
for(int i=1;i<=n;i++){
scanf("%lf%lf",&l,&r);
card[i].S.x=l;
card[i].S.y=y1;
card[i].E.x=r;
card[i].E.y=y2;
}
memset(sum,0,sizeof(sum));
for(int i=1;i<=m;i++)
{
point p;
scanf("%lf%lf",&p.x,&p.y);
for(int j=0;j<=n;j++)
{
///判断点是不是夹在第j条和第j+1条线段之间
if(dcmp((area2(p,card[j].S,card[j].E)))*dcmp((area2(p,card[j+1].S,card[j+1].E)))<0){
sum[j]++;
//
break;
}
}
}
for(int i=0;i<=n;i++)
{
printf("%d: %d\n",i,sum[i]);
}
puts("");
}
return 0;
}
题目链接:http://poj.org/problem?id=2398
题意:跟上一题类似不过这题线段(也就是题目中所说的纸板)不是按照顺序给出的,需要进行排次序,然后题目要求的是有多少个空间里放t个玩具。比如第一组样例中每个空间里都是2个玩具,所以输出2:5.第二组样例有四个空间里有1个玩具,有1个空间里有2个玩具,所以如上输出。
代码如下:
///类似于poj 2318,这里我们采用二分解决方法去做
///向量P和向量Q ,假如P*Q>0 ,P在Q的顺时针方向
///p*Q<0,P在Q的逆时针方向上,
///点a在线段bc的左边,则它们的叉积小于0,点a在线段bc的右边,则它们的叉积大于0
///故我们可以二分隔板,只要叉积小于0的隔板
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=5050;
struct point
{
int x,y;
point(){}
point(int _x,int _y){
x=_x;y=_y;
}
};
point operator + (point a,point b) {return point(a.x+b.x,a.y+b.y);}
point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);}
point operator * (point a,double p) { return point(a.x*p,a.y*p);}
point operator / (point a,double p){ return point(a.x/p,a.y/p);}
struct line{
point S;
point E;
line(){}
line (point _S,point _E){
S=_S;E=_E;
}
}card[maxn];
bool operator < (const point &a,const point &b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
const double esp=1e-5;
int dcmp(double x){
if(fabs(x)<esp) return 0;
else return x<0?-1:1;
}
bool operator == (const point &a,const point &b){
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Cross(point a,point b) { return a.x*b.y-a.y*b.x;}
double area2(point a,point b, point c) {return Cross(b-a,c-a);}
bool cmp(line a,line b){
return a.S.x<b.S.x;
}
int ans[maxn],num[maxn];///ans[i]表示有多少个玩具在第i块空间,num[i]表示空间内有i个玩具的有多少个空间
int main()
{
int n,m;
double x1,y1,x2,y2;
while(scanf("%d",&n)&&n)
{
scanf("%d%lf%lf%lf%lf",&m,&x1,&y1,&x2,&y2);
double Ui,Li;
for(int i=0;i<n;i++){
scanf("%lf%lf",&Ui,&Li);
card[i]=line(point(Ui,y1),point(Li,y2));
}
card[n]=line(point(x2,y1),point(x2,y2));
sort(card,card+n+1,cmp);
double x,y;
memset(ans,0,sizeof(ans));
point p;
while(m--)
{
scanf("%lf%lf",&x,&y);
p=point(x,y);
int L=0,R=n;
int item;
while(L<=R) ///二分
{
int mid=(L+R)/2;
if(dcmp(area2(p,card[mid].S,card[mid].E))<0){ ///满足条件,继续往左缩
item=mid;
R=mid-1;
}
else L=mid+1;
}
// printf("item=%d\n",item);
ans[item]++;
}
memset(num,0,sizeof(num));
for(int i=0;i<=n;i++)
{
// printf("ans[%d]=%d\n",i,ans[i]);
if(ans[i]) num[ans[i]]++;
}
printf("Box\n");
for(int i=1;i<=n;i++)
if(num[i]) printf("%d: %d\n",i,num[i]);
}
return 0;
}
我的标签:不拿奖,誓不成人。