ZOJ_3364_Black and White(巧算方格图形面积)

Black and White
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu

Description

Consider an infinite chessboard. Introduce a coordinate system on it in such a way that chessboard cells are unit squares with integer corner coordates. Let the cells be colored black and white like on the standard chessboard, let the cell with bottom left corner at (0,0) be colored black.

Somebody has drawn a closed polyline on the board. The vertices of the polyline are in the corners of the cells and its sides are parallel to the coordinate axes. It's interesting, what is the number of black and white cells inside the polyline. Find that out.

Input

The first line of the input file contains n --- the number of vertices of the polyline (1 ≤ n ≤ 50000). The following n lines contain the coordinates of the vertices in counter-clockwise order. Coordinates are integer and do not exceed 109 by their absolute values. Polyline has no self-intersections and no self-touchings.

There are multiple cases. Process to the end of file.

Output

Output two numbers: b and w --- the number of black and white cells inside the polyline repectively.

Sample Input

12
1 0
2 0
2 1
3 1
3 2
2 2
2 3
1 3
1 2
0 2
0 1
1 1

Sample Output

1 4

题型:计算几何


题意:

 在一个类似于国际象棋的坐标系中,给出一系列逆时针摆布的点的坐标,这些点之间相连成一个多边形,多边形的边平行于X轴或者Y轴,求出多边形内黑色方块与白色方块的个数。


分析:

 在比赛时打算,将几何体分成一层一层的宽为1,长度为每一层两边最大x之差的矩形,然后通过一层一层的来算得到结果,结果发现如果是长的像城墙一样的几何体就不管用了。

 后来,考虑到所有的点是按逆时针输入的,想可以将这些点遍历一遍,先来分析一下几何体在X轴上方的情况,对于两个点(x1,y1),(x2,y2),若y1==y2,可以计算出(x1,y1)、(x2,y2)、(x1,0)、(x2,0)这四个点围成的矩形中黑色与白色方块的个数,当点的方向是从右向左市,就加上其矩形的黑色块数与白色块数;当点的走向是从左向右时,就减去其矩形的黑色块数与白色块数,最终的结果就是要求的答案。这样的想法是对的,可是我一直在WA。

下附WA代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int x[56789];
int y[56789];
long long b,w;
int main(){
    int n;
    while(~scanf("%d",&n)){
        b=0;
        w=0;
        for(int i=0;i<n;i++){
            scanf("%d%d",&x[i],&y[i]);
        }
        for(int i=1;i<n;i++){
            if(x[i]<x[i-1]&&y[i]==y[i-1]){
                if(y[i]>=0){
                    if((x[i-1]-x[i])*y[i]%2==0){
                        b+=(x[i-1]-x[i])*y[i]/2;
                        w+=(x[i-1]-x[i])*y[i]/2;
                    }
                    else{
                        b+=(x[i-1]-x[i])*y[i]/2;
                        w+=(x[i-1]-x[i])*y[i]/2;
                        if(((y[i]%2==1)&&(x[i]%2==0))||((y[i]%2==0)&&(x[i]%2==1)))
                            b++;
                        else w++;
                    }
                }
                else{
                    if((x[i-1]-x[i])*(-y[i])%2==0){
                        b-=(x[i-1]-x[i])*(-y[i])/2;
                        w-=(x[i-1]-x[i])*(-y[i])/2;
                    }
                    else{
                        b-=(x[i-1]-x[i])*(-y[i])/2;
                        w-=(x[i-1]-x[i])*(-y[i])/2;
                        if((((-y[i])%2==1)&&(x[i]%2==0))||(((-y[i])%2==0)&&(x[i]%2==1)))
                            w--;
                        else b--;
                    }
                }
            }
            else if(x[i]>x[i-1]&&y[i]==y[i-1]){
                if(y[i]>=0){
                    if((x[i]-x[i-1])*y[i]%2==0){
                        b-=(x[i]-x[i-1])*y[i]/2;
                        w-=(x[i]-x[i-1])*y[i]/2;
                    }
                    else{
                        b-=(x[i]-x[i-1])*y[i]/2;
                        w-=(x[i]-x[i-1])*y[i]/2;
                        if(((y[i]%2==1)&&(x[i-1]%2==0))||((y[i]%2==0)&&(x[i-1]%2==1)))
                            b--;
                        else w--;
                    }
                }
                else{
                    if((x[i]-x[i-1])*(-y[i])%2==0){
                        b+=(x[i]-x[i-1])*(-y[i])/2;
                        w+=(x[i]-x[i-1])*(-y[i])/2;
                    }
                    else{
                        b+=(x[i]-x[i-1])*(-y[i])/2;
                        w+=(x[i]-x[i-1])*(-y[i])/2;
                        if((((-y[i])%2==1)&&(x[i-1]%2==0))||(((-y[i])%2==0)&&(x[i-1]%2==1)))
                            w++;
                        else b++;
                    }
                }
            }
            //cout<<"b="<<b<<" "<<"w="<<w<<endl;
        }
        if(x[n-1]>x[0]&&y[0]==y[n-1]){
            if(y[0]>=0){
                if((x[n-1]-x[0])*y[0]%2==0){
                    b+=(x[n-1]-x[0])*y[0]/2;
                    w+=(x[n-1]-x[0])*y[0]/2;
                }
                else{
                    b+=(x[n-1]-x[0])*y[0]/2;
                    w+=(x[n-1]-x[0])*y[0]/2;
                    if(((y[0]%2==1)&&(x[0]%2==0))||((y[0]%2==0)&&(x[0]%2==1)))
                        b++;
                    else w++;
                }
            }
            else{
                if((x[n-1]-x[0])*(-y[0])%2==0){
                    b-=(x[n-1]-x[0])*(-y[0])/2;
                    w-=(x[n-1]-x[0])*(-y[0])/2;
                }
                else{
                    b-=(x[n-1]-x[0])*(-y[0])/2;
                    w-=(x[n-1]-x[0])*(-y[0])/2;
                    if((((-y[0])%2==1)&&(x[0]%2==0))||(((-y[0])%2==0)&&(x[0]%2==1)))
                        w--;
                    else b--;
                }
            }
        }
        else if(x[n-1]<x[0]&&y[0]==y[n-1]){
            if(y[0]>=0){
                if((x[0]-x[n-1])*y[0]%2==0){
                    b-=(x[0]-x[n-1])*y[0]/2;
                    w-=(x[0]-x[n-1])*y[0]/2;
                }
                else{
                    b-=(x[0]-x[n-1])*y[0]/2;
                    w-=(x[0]-x[n-1])*y[0]/2;
                    if(((y[0]%2==1)&&(x[n-1]%2==0))||((y[0]%2==0)&&(x[n-1]%2==1)))
                        b--;
                    else w--;
                }
            }
            else{
                if((x[0]-x[n-1])*(-y[0])%2==0){
                    b-=(x[0]-x[n-1])*(-y[0])/2;
                    w-=(x[0]-x[n-1])*(-y[0])/2;
                }
                else{
                    b-=(x[0]-x[n-1])*(-y[0])/2;
                    w-=(x[0]-x[n-1])*(-y[0])/2;
                    if((((-y[0])%2==1)&&(x[n-1]%2==0))||(((-y[0])%2==0)&&(x[n-1]%2==1)))
                        b--;
                    else w--;
                }
            }
            //cout<<"b="<<b<<" "<<"w="<<w<<endl;
        }
        printf("%lld ",b);
        printf("%lld\n",w);
    }
    return 0;
}
/*
4
1 1
4 1
4 4
1 4
4
0 1
0 -2
3 -2
3 1
4
0 0
-3 0
-3 -3
0 -3
*/

 无奈之下,只好另选思路再写,遍历一下这些点,用前一个点与原点围成的矩形的面积减去后一个点与原点围成的矩形的面积,遍历到最后就可以得出这个几何图形的总面积了,然后在求出黑色方块的个数即可。

AC代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int xn,yn,xp,yp;
int x,y;
long long sum;
long long b;
int odd(int x) {
	if(x>=0) return (x+1)/2;
	else return x/2;
}
int even(int x){
	return x-odd(x);
}
void fun(){
    sum+=(long long)xp*yp-(long long)xn*yn;
    b+=(long long)odd(xp)*odd(yp)+(long long)even(xp)*even(yp)-((long long)odd(xn)*odd(yn)+(long long)even(xn)*even(yn));
    return;
}
int main(){
    while(~scanf("%d",&n)){
        sum=0;
        b=0;
        scanf("%d%d",&x,&y);
        xp=x;
        yp=y;
        n--;
        while(n--){
            scanf("%d%d",&xn,&yn);
            if(yn==yp)
                fun();
            xp=xn;
            yp=yn;
        }
        xn=x;
        yn=y;
        if(yn==yp)
            fun();
        sum-=b;
		printf("%lld ",llabs(b));
        printf("%lld\n",llabs(sum));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值