• fzu 1015 土地划分(判断线段相交+求出交点+找规律)


    链接:http://acm.fzu.edu.cn/problem.php?pid=1015

     Problem 1015 土地划分

    Accept: 714    Submit: 1675
    Time Limit: 1000 mSec    Memory Limit : 32768 KB

     Problem Description

    在Dukeswood这块土地上生活着一个富有的农庄主和他的几个孩子。在他临终时,他想把他的土地分给他的孩子。他有许多农场,每个农场都是一块矩形土地。他在农场地图上划上一些直线将矩形分成若干块。当他划直线时,他总是从矩形边界上的某一点划到另一个矩形边界上的点,这条线的结束点将成为下一条线的起始点。他划线时从不会让任三线共点。例如图1是某一种划分结果。


    图1

    划分的起始点和结束点均以五角星标记。当他完成划分后,他想要数一下划出的土地的块数以确保每个孩子都有一块地。例如,图1中土地被划分成18块。然而这个庄主由于年迈常会数错,因而他寻求你的帮助。

    请写一个程序,输入原来的土地尺寸及线段的位置,输出划分出的土地块数。

     Input

    输入文件有多组数据组成。每组数据格式如下:
    第一行输入地图的宽度w (1<=w<=1000)和高度 h (1<=h<=1000),均为整数。
    第二行输入线段数L (1<=L<=50)。
    以下L+1行每行一个整数坐标(Xi,Yi),庄主划的线段为(Xi,Yi)-(Xi+1,Yi+1),i=1,2,…,L。当然(Xi,Yi)必定在矩形的边界上。
    最后一组数据w=h=0,标志文件结束,不需要处理。

     Output

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

     Sample Input

    18 12
    8
    2 0
    6 12
    10 0
    18 9
    15 12
    0 6
    14 0
    10 12
    0 9
    7 6
    6
    2 0
    5 6
    7 3
    0 3
    3 0
    3 6
    0 5
    0 0

     Sample Output

    18
    11
     
     
     
    /。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。/。
         看到此题,可联想到组合几何中的一个问题,求平面上n条直线最多可以将平面分成多少块
    首先分析直线划分区域的情况,根据已知的结论:平面上的n条直线最多可以将平面分成 f ( n )个区域,其中 f(n)=(n^2+n+2)/2.
    实际上,重点是讨论如何得出这个结论的过程
    方法————数学归纳法
    当n=1时,f(1)=(1^2+1+2)/2=2显然成立,即一条直线把平面分成两个区域。
    -----------------------------------------------------------------------------------
    假设,对所有的n<k的n,均有f(n)=(n^2+n+2)/2。考虑n=k
    新的直线L做多可以和原来的n-1条直线有n-1个交点,这n-1个交点将直线分成了n段,其中
    n-2段为线段,两段为射线。这n段线将其所在的n个区域一分为二,这样就增加了n个
    区域,所以f(n)=f(n-1)+n。再由归纳假设,f(n-1)=((n-1)^2+(n-1)+2)/2,因而有:
    f(n)=((n-1)^2+(n-1)+2)/2+n=(n^2+n+2)/2
    因此,对所有的正整数n,均有f(n)=(n^2+n+2)/2
     -----------------------------------------------------------------------------------
    具体推导过程看这里吧:http://wenku.baidu.com/view/15733b0b79563c1ec5da71cf.html
    经过推导,可以得出结论,f(L)=1+T+L
    就是不在矩形边上的交点个数T+线段的条数L+1即为答案
    下面给出代码:
      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <math.h>
      5 #include <iostream>
      6 #include <algorithm>
      7 #define eps 1e-6
      8 
      9 struct point
     10 {
     11     double x,y;
     12 };
     13 
     14 struct beline
     15 {
     16     point a,b;
     17 };
     18 
     19 using namespace std;
     20 
     21 point p[5000];
     22 
     23 bool dy(double x,double y)
     24 {
     25     return x > y+eps;
     26 }
     27 bool xy(double x,double y)
     28 {
     29     return x < y-eps;
     30 }
     31 bool xyd(double x,double y)
     32 {
     33     return x < y+eps;
     34 }
     35 bool dyd(double x,double y)
     36 {
     37     return x > y-eps;
     38 }
     39 double dd(double x,double y)
     40 {
     41     return fabs(x-y) < eps;
     42 }
     43 
     44 double crossProduct(point a,point b,point c)
     45 {
     46     return (c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x);
     47 }
     48 
     49 bool onSegment(point a,point b,point c)
     50 {
     51     double maxx=max(a.x,b.x);
     52     double maxy=max(a.y,b.y);
     53     double minx=min(a.x,b.x);
     54     double miny=min(a.y,b.y);
     55     if(dd(crossProduct(a,b,c),0.0)&&dyd(c.x,minx)&&xyd(c.x,maxx)
     56         &&dyd(c.y,miny)&&xyd(c.y,maxy))
     57         return true;
     58     return false;
     59 }
     60 
     61 bool segIntersect(point p1,point p2,point p3,point p4)
     62 {
     63     double d1 = crossProduct(p3,p4,p1);
     64     double d2 = crossProduct(p3,p4,p2);
     65     double d3 = crossProduct(p1,p2,p3);
     66     double d4 = crossProduct(p1,p2,p4);
     67     if(xy(d1*d2,0.0)&&xy(d3*d4,0.0))
     68         return true;
     69     if(dd(d1,0.0)&&onSegment(p3,p4,p1))
     70         return true;
     71     if(dd(d2,0.0)&&onSegment(p3,p4,p2))
     72         return true;
     73     if(dd(d3,0.0)&&onSegment(p1,p2,p3))
     74         return true;
     75     if(dd(d4,0.0)&&onSegment(p1,p2,p4))
     76         return true;
     77     return false;
     78 }
     79 
     80 point intersectpoint(beline u,beline v)
     81 {
     82     point ans=u.a;
     83     double t = ((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))/
     84     ((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
     85     ans.x+=(u.b.x-u.a.x)*t;
     86     ans.y+=(u.b.y-u.a.y)*t;
     87     return ans;
     88 }
     89 int main()
     90 {
     91     int n,m,i,j,k;
     92     beline li[55];
     93     while(scanf("%d%d",&n,&m)!=EOF&&n||m)
     94     {
     95         scanf("%d",&k);
     96         for(i=0;i<=k;i++)
     97         {
     98             scanf("%lf%lf",&p[i].x,&p[i].y);
     99         }
    100         for(i=0;i<k;i++)
    101         {
    102             li[i].a.x=p[i].x;
    103             li[i].a.y=p[i].y;
    104             li[i].b.x=p[i+1].x;
    105             li[i].b.y=p[i+1].y;
    106         }
    107 
    108         int sum=0;
    109         for(i=0;i<k;i++)
    110         {
    111             for(j=i+1;j<k;j++)
    112             {
    113                 if(segIntersect(li[i].a,li[i].b,li[j].a,li[j].b))
    114                 {
    115                     point tmp;
    116                     tmp=intersectpoint(li[i],li[j]);
    117                     if(dy(tmp.x,0.0)&&xy(tmp.x,(double)n)&&dy(tmp.y,0.0)&&xy(tmp.y,(double)m))
    118                     {
    119                         sum++;
    120                     }
    121                 }
    122             }
    123         }
    124         printf("%d
    ",sum+k+1);
    125     }
    126     return 0;
    127 }
    View Code
     
     
     
     
     
     
  • 相关阅读:
    Java中常见的几种加密算法
    关于redis中过期的key的处理
    Redis 的内存淘汰策略
    AES加密算法原理(加密过程)
    springboot中从配置文件中读取相关参数值
    springboot中切换配置(多个配置文件--生产、开发、测试)
    mysql跨库查询数据
    SpringBoot2.0 的默认连接池----Hikari
    Druid连接池中的缓存机制
    Opus编解码练习
  • 原文地址:https://www.cnblogs.com/ccccnzb/p/3863327.html
Copyright © 2020-2023  润新知