Fork me on github

poj 2398 Toy Storage(计算几何)

  • 题目传送门:poj 2398 Toy Storage

  • 题目大意:一个长方形的箱子,里面有一些隔板,每一个隔板都可以纵切这个箱子。隔板将这个箱子分成了一些隔间。向其中扔一些玩具,每个玩具有一个坐标,求有\(t​\)个玩具的隔间数(对\(t>0​\)都要输出)。

  • 题目分析:涉及到计算几何的知识是求点在线的哪一侧。可以利用叉积来做。取点\(A\)到隔板的上端点\(B\)的向量\(\vec{AB}\)叉乘点\(A\)到隔板的下端点\(C\)的向量\(\vec{AC}\)。叉积的公式\(\vec a\times \vec b=|\vec a||\vec b|sin(\vec a,\vec b)\)里是有一个\(sin(\vec a,\vec b)\)的。可见若点\(A\)\(BC\)的左侧,\((\vec{AB},\vec{AC})>\pi\)(右手法则的角度),故\(sin(\vec{AB},\vec{AC})<0\)\(\vec{AB}\times \vec{AC}<0\)。反之,点\(A\)\(BC\)右侧,\(\vec{AB}\times \vec{AC}>0\)。这样就可以二分求每个玩具在哪个隔间里。

  • #include <cstdio>
    #include <cmath>
    #include <ctime>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    typedef long long LL;
    const int maxn = 1000;
    
    using namespace std;
    
    struct tPoint
    {
        int x, y;
    };
    
    struct tCard
    {
        tPoint a, b;
        bool operator<(const tCard& y) const
        {
            if(a.x==y.a.x)
                return b.x<y.b.x;
            return a.x<y.a.x;
        }
    };
    tCard card[maxn+10];
    
    int Multi(tPoint p1, tPoint p2, tPoint p0)
    {
        return (p1.x-p0.x) * (p2.y-p0.y) - (p2.x-p0.x) * (p1.y-p0.y);
    }
    
    int bSearch(tPoint p, int n)
    {
        int l=1, r=n;
        while(l<=r)
        {
            int mid = (l+r)/2;
            if(Multi(card[mid].a, card[mid].b, p)>0)
                l = mid+1;
            else
                r = mid-1;
        }
        return l;
    }
    
    int num[maxn+10];//partition[i]含的玩具数
    int parti[maxn+10];//含i个玩具的partition数
    
    int main()
    {
        int n, m, x1, y1, x2, y2;
        while(scanf("%d", &n), n)
        {
            scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
            for(int i=1,u,l; i<=n; i++)
            {
                scanf("%d%d", &u, &l);
                card[i] = (tCard){(tPoint){u,y1},(tPoint){l,y2}};
            }
            card[n+1] = (tCard){(tPoint){x1,y1},(tPoint){x1,y2}};
            card[n+2] = (tCard){(tPoint){x2,y1},(tPoint){x2,y2}};
            sort(card+1, card+1+n+2);
    
            memset(num, 0, sizeof(num));
            for(int i=1; i<=m; i++)
            {
                tPoint p;
                scanf("%d%d", &p.x, &p.y);
                int part = bSearch(p, n+2) - 1;
                num[part]++;
            }
    
            memset(parti, 0, sizeof(parti));
            for(int i=1; i<=n+1; i++)
                parti[num[i]]++;
    
            printf("Box\n");
            for(int i=1; i<=maxn; i++)
            {
                if(parti[i])
                    printf("%d: %d\n", i, parti[i]);
            }
        }
        return 0;
    }
    
    
posted @ 2019-03-31 17:27  acboyty  阅读(245)  评论(0编辑  收藏  举报