矩形分割

题目链接:http://noi.openjudge.cn/ch0111/03/

一个二分的题目,估计是数据类型选择不当,折腾了好多天。所以,以后记得尽管使用long  long类型数据呵呵

描述

平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R)。大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠。所有矩形的顶点都是整点。要求画一根平行于y轴的直线x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小。并且,要使得大矩形在直线左边的的面积尽可能大。注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧。

输入

第一行是整数R,表示大矩形的右上角坐标是(R,R) (1 <= R <= 1,000,000)。
接下来的一行是整数N,表示一共有N个小矩形(0 < N <= 10000)。
再接下来有N 行。每行有4个整数,L,T, W 和 H, 表示有一个小矩形的左上角坐标是(L,T),宽度是W,高度是H (0<=L,T <= R, 0<w,h <="R)."

小矩形不会有位于大矩形之外的部分。

输出

输出整数n,表示答案应该是直线 x=n。 如果必要的话,x=R也可以是答案。样例输入

1000
2
1 1 2 1
5 1 2 1

样例输出

5

我的思路:对解区间[0,R]做二分,查找可能的解。(假设每一次二分计算的中间点是解,然后做验证。然后在寻找更合理的解。)注意:long long类型数据要使用%lld输入输出。暂时还有一个疑惑,就是末尾的绝对值部分。(这个下面再提)AC代码:
 1 #include<stdio.h>
 2 #include<math.h>
 3 struct obj
 4 {
 5     long long left,top,w,h;//左上角横、纵坐标和宽、高值
 6     long long rx;//右下角顶点的横坐标
 7     long long s;//面积
 8 };
 9 long long sigema(struct obj a[],int n,int mid)
10 {
11     int i;
12     long long sum1,sum2;
13     sum1=sum2=0;
14     for(i=0;i<n;i++)
15     {
16         if(a[i].rx<=mid) sum1+=a[i].s; //该矩形属左侧
17         else if(a[i].left>=mid) sum2+=a[i].s;//属右侧
18         else
19         {
20             sum1+=a[i].h*(mid-a[i].left);
21             sum2+=a[i].h*(a[i].rx-mid);
22         }
23     }
24     return sum1-sum2;
25 }
26 int main()
27 {
28     long long r,n,i;
29     struct obj a[10005];
30     long long minx,maxx,mid,ans,maxx2;
31     long long temp,temp1,temp2;
32
33     scanf("%lld%lld",&r,&n);
34     for(i=0;i<n;i++)
35     {
36         scanf("%lld%lld%lld%lld",&a[i].left,&a[i].top,&a[i].w,&a[i].h);
37         a[i].s=a[i].w*a[i].h;
38         a[i].rx=a[i].left+a[i].w;
39         if(i==0)  maxx2=a[i].rx;
40         else
41         {
42             if(a[i].rx>maxx2) maxx2=a[i].rx;
43         }
44     }
45     minx=0;
46     maxx=r;
47     while(minx+1<maxx)//需要二分枚举的答案是整数,所以可以用这个方式结束
48     {
49         mid=(minx+maxx)/2;
50         temp=sigema(a,n,mid);
51         if(temp>0) maxx=mid;
52         else if(temp<=0) minx=mid;
53     }
54
55     temp1=sigema(a,n,minx);
56     temp2=sigema(a,n,maxx);
57     /*if(fabs(temp1)<fabs(temp2)) ans=minx;
58     else ans=maxx;*/
59     if( temp1<temp2)
60     {
61         if(temp1>=0) ans=minx;
62         else ans=maxx;
63     }
64     else if(temp1>temp2)
65     {
66         if(temp2>=0) ans=maxx;
67         else ans=minx;
68     }
69     else ans=maxx;
70     if(ans==maxx2) ans=r;
71     printf("%lld\n",ans);
72     return 0;
73 }

这个题目一直有一个疑惑。最开始的时候题目并未有提到有一个大矩形,题目的要求仅仅是“左边部分小矩形的面积之和不小于右边部分小矩形面积之和”。后来题目做了修改,增加了大矩形的约束。参看了别人的代码,也自己验证过,代码后面的if语句里面的绝对值竟然在修改题目后还可以通过。就是下面的语句:

if(fabs(temp1)<fabs(temp2)) ans=minx;
else ans=maxx;

  我一直都觉得这个语句只能起到约束题目的第一个条件(小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小),并不能够约束题目的第二个条件(要使得大矩形在直线左边的的面积尽可能大)。因为若是直接取绝对值,不能够保证哪一边的面积比较大,只是能够保证两边的面积差距尽量小。

所以,我在后面代码里面做了修改,用的是这样的代码:
 1 if( temp1<temp2)
 2     {
 3         if(temp1>=0) ans=minx;
 4         else ans=maxx;
 5     }
 6     else if(temp1>temp2)
 7     {
 8         if(temp2>=0) ans=maxx;
 9         else ans=minx;
10     }
11     else ans=maxx;

另外,还要一个地方比较重要,那就是最后一个if语句。

1 if(ans==maxx2) ans=r;
				
时间: 2024-11-12 18:58:51

矩形分割的相关文章

2017.4.23 1.矩形分割

1.矩形分割 (二分) 1000ms 内存限制:  65536kB 描述 平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R).大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠.所有矩形的顶点都是整点.要求画一根平行于y轴的直线x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小.并且,要使得大矩形在直线左边的的面积尽可能大.注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧. 输入 第一行是整数R,表示大矩形的右上

[Offer收割]编程练习赛12 题目3 : 矩形分割

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一块由NxM个单位正方形组成的矩形.现在小Ho在某些单位正方形上画了一道分割线,这条分割线或者是单位正方形的主对角线(用'\'表示),或者是副对角线(用'/'表示). 现在小Hi想知道这些分割线把NxM的矩形分割成了多少块区域. 例如 /\/ 就把2x2的矩形分成了5个区域. /\/\ / \/ 把3x4的矩形分成了7个区域. 输入 第一包含两个整数N和M.(1 <= N, M <= 100) 以下N行每行包

hnu12884 Area Coverage 矩形分割 or 线段树

题意:给你n个二维平面上的矩形,可以两两覆盖,问最后覆盖的总面积为多少 解题思路:1)矩形状分割,可以知道,每多出一个矩形就和前面所有产生的矩形判断,看是有相交,如果有的话,就对前面的矩形进行分割,最多可以分割成8块,因为这个算法是n×n的算法时间复杂度,所以我们还需要在枚举的时候加速,采用引导值(下一个不为0的矩阵的值),最后6700ms过了 解题代码: 1 // File Name: rect1.c 2 // Author: darkdream 3 // Created Time: 2014

多个限制的二分题 poj 矩形分割

openoj 矩形分割 总时间限制:  1000ms  内存限制: 65536kB 描述 平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R).大矩形内部包含一些小矩形,小矩形都平行于坐标轴且互不重叠.所有矩形的顶点都是整点.要求画一根平行于y轴的直线x=k(k是整数) ,使得这些小矩形落在直线左边的面积必须大于等于落在右边的面积,且两边面积之差最小.并且,要使得大矩形在直线左边的的面积尽可能大.注意:若直线穿过一个小矩形,将会把它切成两个部分,分属左右两侧. 输入 第一行是整数R,

hihoCoder 第253周 hiho一下 矩形分割

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi有一块由NxM个单位正方形组成的矩形.现在小Ho在某些单位正方形上画了一道分割线,这条分割线或者是单位正方形的主对角线(用'\'表示),或者是副对角线(用'/'表示). 现在小Hi想知道这些分割线把NxM的矩形分割成了多少块区域. 例如 /\/ 就把2x2的矩形分成了5个区域. /\/\ / \/ 把3x4的矩形分成了7个区域. 输入 第一包含两个整数N和M.(1 <= N, M <= 100) 以下N行每行包

POJ 8208 矩形分割 【二分】

要使两边面积之差最小且保证小矩形直线左边面积大于等于右边面积,在此基础上使大矩形在直线左边的面积尽量大. 想了想后我把这道题分为两步解决,首先找到面积之差的最小值:然后想到一个范围内划直线都是这个最小值,在这个范围内找到最右边的(即保证大矩形左边的面积最大). 第一次二分算面积之差最小值,square(k)返回x=k这条直线左边小矩形的面积,s是所有小矩形的面积:若square(k)>=s-square(k),那面积差最小就在k的左边(包括k),不然就在k+1右边找. 第二次二分的本质是左右矩形

hihocoder offer收割编程练习赛12 C 矩形分割

思路: 模拟,深搜. 实现: 1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 using namespace std; 5 6 const int dx[4] = { 0, 1, 0, -1 }; 7 const int dy[4] = { -1, 0, 1, 0 }; 8 9 int n, m, cnt = 0; 10 int a[305][305]; 11 bool vis[305][3

车牌定位--颜色分割

http://blog.csdn.net/liujia2100/article/details/30845493 车牌定位是车牌识别中第一步,也是最重要的一步. 由于中国车牌种类多样,颜色不一, 再加上车牌经常有污损,以及车牌周围干扰因素太多,都成为了车牌定位的难点. 这里首先使用最简单算法来描述车牌定位,以及他的缺陷和改进. 一.投影法 1.车辆图像信息获取 2.HSV颜色转换 把RGB数据转换成HSV空间图像数据 hsvzation(image,hsv,width,height); 3.HS

poj - 1191 - 棋盘分割(dp)

题意:将一个8*8的棋盘(每个单元正方形有个分值)沿直线(竖或横)割掉一块,留下一块,对留下的这块继续这样操作,总共进行n - 1次,得到n块(1 < n < 15)矩形,每个矩形的分值就是单元正方形的分值的和,问这n个矩形的最小均方差. 题目链接:http://poj.org/problem?id=1191 -->>此题中,均方差比较,等价于方差比较,等价于平方和比较.. 状态:dp[x1][y1][x2][y2][i]表示将(x1, y1)到(x2, y2)的矩形分割i次的最小