矩形分割

简介: 题目链接:http://noi.openjudge.cn/ch0111/03/ 一个二分的题目,估计是数据类型选择不当,折腾了好多天。所以,以后记得尽管使用long  long类型数据呵呵   描述 平面上有一个大矩形,其左下角坐标(0,0),右上角坐标(R,R)。

题目链接: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;



相关文章
|
算法 前端开发
圆和矩形是否有重叠
圆和矩形是否有重叠
95 0
|
2月前
|
Serverless 计算机视觉
语义分割笔记(三):通过opencv对mask图片来画分割对象的外接椭圆
这篇文章介绍了如何使用OpenCV库通过mask图像绘制分割对象的外接椭圆。首先,需要加载mask图像,然后使用`cv2.findContours()`寻找轮廓,接着用`cv2.fitEllipse()`拟合外接椭圆,最后用`cv2.ellipse()`绘制椭圆。文章提供了详细的代码示例,展示了从读取图像到显示结果的完整过程。
69 0
语义分割笔记(三):通过opencv对mask图片来画分割对象的外接椭圆
|
2月前
|
算法 计算机视觉 Python
圆形检测算法-基于颜色和形状(opencv)
该代码实现了一个圆检测算法,用于识别视频中的红色、白色和蓝色圆形。通过将图像从RGB转换为HSV颜色空间,并设置对应颜色的阈值范围,提取出目标颜色的区域。接着对这些区域进行轮廓提取和面积筛选,使用霍夫圆变换检测圆形,并在原图上绘制检测结果。
94 0
|
6月前
|
存储 算法 Python
查找图像轮廓
【6月更文挑战第11天】查找图像轮廓。
60 3
|
7月前
|
计算机视觉
OpenCV(十三):图像中绘制直线、圆形、椭圆形、矩形、多边形和文字
OpenCV(十三):图像中绘制直线、圆形、椭圆形、矩形、多边形和文字
96 0
|
人工智能 算法 BI
|
计算机视觉
OpenCV-最小包围旋转矩形边框cv::minAreaRect
OpenCV-最小包围旋转矩形边框cv::minAreaRect
206 0
|
Rust 自然语言处理 算法
【算法】1725. 可以形成最大正方形的矩形数目(多语言实现)
给你一个数组 rectangles ,其中 rectangles[i] = [li, wi] 表示第 i 个矩形的长度为 li 、宽度为 wi 。 如果存在 k 同时满足 k <= li 和 k <= wi ,就可以将第 i 个矩形切成边长为 k 的正方形。例如,矩形 [4,6] 可以切成边长最大为 4 的正方形。 设 maxLen 为可以从矩形数组 rectangles 切分得到的 最大正方形 的边长。 请你统计有多少个矩形能够切出边长为 maxLen 的正方形,并返回矩形 数目 。
|
人工智能 算法 前端开发
非重叠矩形中的随机点
🎈每天进行一道算法题目练习,今天的题目是“非重叠矩形中的随机点”。
175 0