1. 程式人生 > >poj 2318 TOYS 與 poj 2398 Toy Storage(叉積的應用:點線上段的左邊或者右邊)

poj 2318 TOYS 與 poj 2398 Toy Storage(叉積的應用:點線上段的左邊或者右邊)

題目連結: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;
}



 

 

我的標籤:不拿獎,誓不成人。