POJ 2318 几何初步 + 二分 及其 姊妹题 POJ 2398

来源:互联网 发布:其他设备 网络控制器 编辑:程序博客网 时间:2024/06/11 21:52

叉积+二分


如果toys在当前板的左边 cross(L,toys,U) < 0

反之在右边会 > 0

根据这个,我们进行二分;

为什么最后得到的不是mid而是l呢?

我们来看这张图.

加入现在是 l = 2 , r = 5;mid = 3; toy在4纸板右边,5纸板左边,

执行l = l +1 = 3, r = 5, mid = 4;依然>0 执行, 

l = l + 1 = 4,r = 5, mid = 4; 依然大于0 ,执行

l = l + 1 = 5, r= 5, 退出; 此时l = 5, 之前toy确实在l右边,可是现在在它左边了.(有的情况还是会在右边)

所以我们后面要加一个判断:

if(cross(CardB[r].L, Toys, CardB[r].U) < 0)        N_Toys[l]++;else        N_Toys[l+1]++;

显然,我们同样可以:

if(cross(CardB[r].L, Toys, CardB[r].U) > 0)        N_Toys[r+1]++;else        N_Toys[r]++;

那么,如果利用mid 改怎么改写代码呢?

        for(int i = 0; i < m; i++)        {            l = 0, r = n-1;            scanf("%d%d",&Toys.x,&Toys.y);            while(l <= r)            {                mid = (l + r) >> 1;                if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0)                    l = mid + 1;                else                    r = mid - 1;            }            if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0)                N_Toys[mid+1]++;            else                N_Toys[mid]++;        }

/* *POJ 2318 *fuqiang *几何初步 *2013/8/2*/#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>using namespace std;const int maxn = 5000+3;const double PI = 4.0*atan(1.0);const double eps = 1e-8;struct point{    int x;    int y;} Toys;struct Line{    point U;    point L;} CardB[maxn];int N_Toys[maxn];int cross(const point &p0, const point &p1, const point &p2)  //计算叉积{    return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);}int main(){#ifndef ONLINE_JUDGE    freopen("in","r",stdin);#endif    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 = 0; i < n; i++)        {            scanf("%d%d", &CardB[i].U.x, &CardB[i].L.x);            CardB[i].U.y = y1;            CardB[i].L.y = y2;        }        memset(N_Toys,0,sizeof(N_Toys));        int l, r, mid, ans, p;        for(int i = 0; i < m; i++)        {            l = 0, r = n-1;            scanf("%d%d",&Toys.x,&Toys.y);            while(l < r)            {                mid = (l + r) >> 1;                if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0)                    l = mid + 1;                else                    r = mid;            }            if(cross(CardB[r].L, Toys, CardB[r].U) < 0)                N_Toys[l]++;            else                N_Toys[l+1]++;        }        for(int i = 0; i <= n; i++)        {            printf("%d: %d\n",i,N_Toys[i]);        }        printf("\n");    }}

还有个更好的点子,别人的代码:

将最后一个点也作为纸板,此时 我们只需要返回l:

while (l <= r){    mid = (l + r) >> 1;    if ( cal (low[mid], high[mid], cc) > 0 )        l = mid + 1;    else r = mid - 1;    }    return l;}

POJ 2398

加个排序,统计后输出,注意t>0

/* *POJ 2318 *fuqiang *几何初步 *2013/8/2*/#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>using namespace std;const int maxn = 5000+3;const double PI = 4.0*atan(1.0);const double eps = 1e-8;struct point{    int x;    int y;} Toys;struct Line{    point U;    point L;} CardB[maxn];int N_Toys[maxn];int cross(const point &p0, const point &p1, const point &p2)  //计算叉积{    return (p1.x-p0.x)*(p2.y-p0.y) - (p2.x-p0.x)*(p1.y-p0.y);}int cmp(Line a, Line b)//sort...{    return a.L.x < b.L.x;}int main(){#ifndef ONLINE_JUDGE    freopen("in","r",stdin);#endif    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 = 0; i < n; i++)        {            scanf("%d%d", &CardB[i].U.x, &CardB[i].L.x);            CardB[i].U.y = y1;            CardB[i].L.y = y2;        }        sort(CardB,CardB+n,cmp); //sort        memset(N_Toys,0,sizeof(N_Toys));        int l, r, mid, ans, p;        for(int i = 0; i < m; i++)        {            l = 0, r = n-1;            scanf("%d%d",&Toys.x,&Toys.y);            while(l <= r)            {                mid = (l + r) >> 1;                if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0)                    l = mid + 1;                else                    r = mid - 1;            }            if(cross(CardB[mid].L, Toys, CardB[mid].U) > 0)                N_Toys[mid+1]++;            else                N_Toys[mid]++;        }        sort(N_Toys,N_Toys+n+1);        printf("Box\n");        int st = 0;        while(N_Toys[st] == 0)            st++;        for(int i = st; i <= n; )        {            int num = 1;            printf("%d: ",N_Toys[i]);            for(int j = i++; j <= n; j++,i++)            {                if(N_Toys[i]==N_Toys[j])                    num++;                else                    break;            }            printf("%d\n",num);        }//        printf("\n");    }}


原创粉丝点击