zl程序教程

您现在的位置是:首页 >  其它

当前栏目

【u217】土地划分

划分 土地
2023-09-14 09:03:47 时间

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】
在Dukeswood这块土地上生活着一个富有的农庄主和他的几个孩子。在他临终时,他想把他的土地分给他的孩子。他有许多农场,每个农场
都是一块矩形土地。他在农场地图上划上一些直线将矩形分成若干块。当他划直线时,他总是从矩形边界上的某一点划到另一个矩形边
界上的点,这条线的结束点将成为下一条线的起始点。他划线时从不会让任三线共点。例如下图是某一种划分结果。
这里写图片描述
划分的起始点和结束点均以五角星标记。当他完成划分后,他想要数一下划出的土地的块数以确保每个孩子都有一块地。例如,上图中土地
被划分成18块。然而这个庄主由于年迈常会数错,因而他寻求你的帮助。
请写一个程序,输入原来的土地尺寸及线段的位置,输出划分出的土地块数。

【输入格式】

第一行输入地图的宽度w(1<=w<=100)和高度h(1<=h<=100),均为整数。
第二行输入线段数L(1<=L<=15)。
以下L+1行每行一个整数坐标(Xi,Yi),庄主划的线段为(Xi,Yi)-(Xi+1,Yi+1),i=1,2,…,L。当然(Xi,Yi)必定在矩形的边界上。

【输出格式】
对于给定的输入,输出一行仅含一个数,即划分出的土地块数。

【数据范围】

Sample Input1
19 12
8
2 0
6 12
11 0
19 9
17 12
0 7
15 0
11 12
0 10

Sample Output1
18

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=u217

【题解】

一开始,如果一条直线都没有;
则平面数为1;
这里写图片描述
画一条线则平面数递增1;变成2
这里写图片描述
再划一条线(不与任何直线相交);则平面数再增加;变成3;
这里写图片描述
如果再划一条线;和之前的1条线相交,则平面数不是增加1而是增加2了;则变成5;
这里写图片描述
如果这条线变一下,和之前的2条线相交,则平面数变成增加3;则变成6;即
这里写图片描述
则枚举线段i;再枚举线段1到i-1
总结一下就是,出现一条线段,平面数递增,如果这条线段和之前的线段相交平面数再递增(相交的坐标要在平面内,所以有一个坐标的判断,且不能在边界上。)
已知两条线段相交;
且知道
x0,y0,x1,y1
x2,y2,x3,y3;
相交的那个程序里面有给出交点坐标;
要把那些垂直和横着的情况去掉;

【完整代码】

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

void rel(LL &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t) && t!='-') t = getchar();
    LL sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

void rei(int &r)
{
    r = 0;
    char t = getchar();
    while (!isdigit(t)&&t!='-') t = getchar();
    int sign = 1;
    if (t == '-')sign = -1;
    while (!isdigit(t)) t = getchar();
    while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
    r = r*sign;
}

const int MAXN = 16+5;
const int dx[5] = {0,1,-1,0,0};
const int dy[5] = {0,0,0,-1,1};
const double pi = acos(-1.0);

struct abc
{
    int a0,b0,a1,b1;
};


abc xd[MAXN];
int w,h,l;
LL ans = 0;

bool cross(int i,int j)
{
    abc z = xd[i],y = xd[j];
    if (z.a1==z.a0 && y.a1==y.a0) return false;
    if  ((z.b1-z.b0)*(y.a1-y.a0)==(z.a1-z.a0)*(y.b1-y.b0))
        return false;
    else
    {
        double xx,yy;
        double x0 = z.a0,y0 = z.b0,x1 = z.a1,y1= z.b1;
        double x2 = y.a0,y2 = y.b0,x3 = y.a1,y3 = y.b1;
        //- |
        if (y1==y0 && x3==x2)
        {
            xx = x2,yy = y1;
        }
        else//-- --
            if (y1==y0 && y3==y2)
                return false;
            else//| -
                if (x1==x0 && y3==y2)
                {
                    xx = x1,yy = y2;
                }
                else//  -
                    if (y3==y2)
                    {
                        yy = y2;
                        xx = x0+(x1-x0)*(yy-y0)/(y1-y0);
                    }
                    else
                    {
                        yy = ( (y0-y1)*(y3-y2)*x0 + (y3-y2)*(x1-x0)*y0 + (y1-y0)*(y3-y2)*x2 + (x2-x3)*(y1-y0)*y2 ) / ( (x1-x0)*(y3-y2) + (y0-y1)*(x3-x2) );
                        xx = x2 + (x3-x2)*(yy-y2) / (y3-y2);
                    }
        if (0 < xx && xx<w && 0<yy&&yy<h)
            return true;
        return false;
    }
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    rei(w);rei(h);
    rei(l);
    rei(xd[1].a0);rei(xd[1].b0);
    rep1(i,1,l)
    {
        rei(xd[i].a1);rei(xd[i].b1);
        xd[i+1].a0 = xd[i].a1,xd[i+1].b0 = xd[i].b1;
    }
    ans = 1;
    rep1(i,1,l)
    {
        ans++;
        rep1(j,1,i-1)
            if (cross(i,j))
                ans++;
    }
    cout << ans << endl;
    return 0;
}