NOIP2002 矩形覆盖
题四 矩形覆盖(存盘名NOIPG4)
[问题描述]:
在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示。例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一。
这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴。当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4。问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢。约定:覆盖一个点的矩形面积为 0;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。
[输入]:
键盘输人文件名。文件格式为
n k
xl y1
x2 y2
... ...
xn yn (0<=xi,yi<=500)
[输出]:
输出至屏幕。格式为:
一个整数,即满足条件的最小的矩形面积之和。
[输入输出样例]
d.in :
4 2
1 1
2 2
3 6
0 7
屏幕显示:
4
【思路】
回溯法。
搜索依次确定每个点属于哪一个矩形,时间复杂度为O(50^4)。最优解剪枝+如果相交则剪枝。
在网上看到了DP的做法:
f[i][j][k]=min{ f[i][l][k-1]+S(l+1,j) }
算法并不完美(只出现了矩形包含的点连续的情况,还有可能不连续),因为数据比较弱所以才能AC,但不失为一种可以借鉴的思路。
【dfs代码】
#include<iostream>
#include<cstring>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int maxn = +;
struct Matrix{
int a,b,c,d;
bool flag;
Matrix() { flag=false; }
}re[]; int x[maxn],y[maxn];
int n,m,ans; bool in(int x,int y,Matrix A) {
return (x>=A.a && x<=A.b && y>=A.c && y<=A.d);
} bool can(int i,int j) {
bool ans=;
if(in(re[i].a,re[i].c,re[j])) return ;
if(in(re[i].a,re[i].d,re[j])) return ;
if(in(re[i].b,re[i].c,re[j])) return ;
if(in(re[i].b,re[i].d,re[j])) return ;
return ;
} void dfs(int d) {
Matrix tmp;
int sum=;
FOR(i,,m)
if(re[i].flag)
{
sum += (re[i].b-re[i].a)*(re[i].d-re[i].c);
FOR(j,i+,m)
if(re[j].flag && (can(i,j))) return ;
} if(sum>=ans) return ;
if(d>n) { ans=sum; return ; }
FOR(i,,m) {
tmp=re[i];
if(!re[i].flag) {
re[i].flag=;
re[i].a=re[i].b=x[d];
re[i].c=re[i].d=y[d];
}
else {
re[i].a=min(re[i].a,x[d]);
re[i].b=max(re[i].b,x[d]);
re[i].c=min(re[i].c,y[d]);
re[i].d=max(re[i].d,y[d]);
}
dfs(d+);
re[i]=tmp;
}
} int main() {
ios::sync_with_stdio(false);
cin>>n>>m;
FOR(i,,n) cin>>x[i]>>y[i];
ans=1e9;
dfs();
cout<<ans;
return ;
}
【dp代码】
#include<iostream>
#define Max 1000000
using namespace std; int n,m,ans=Max,x[],y[],f[][][]={}; int High(int i,int j){
int maxh=,minh=,temp=i;
while(temp<=j)
maxh=max(maxh,y[temp++]);
temp=i;
while(temp<=j)
minh=min(minh,y[temp++]);
return maxh-minh;
} void Dp(){
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
for(int k=;k<=m;++k)
f[i][j][k]=Max; for(int i=;i<=n;++i)
for(int j=i+;j<=n;++j)
f[i][j][]=(x[j]-x[i])*High(i,j);
for(int i=;i<=n;++i)
for(int k=;k<=m;++k)
f[i][i][k]=; for(int k=;k<=m;++k)
for(int i=;i<=n;++i)
for(int j=i+;j<=n;++j)
for(int l=i+;l<=j;++l)
f[i][j][k]=min(f[i][j][k],f[i][l-][k-]+(x[j]-x[l])*High(l,j)); ans=min(ans,f[][n][m]);
} int main()
{
cin>>n>>m;
for(int i=;i<=n;++i)
cin>>x[i]>>y[i]; for(int i=;i<=n;++i)
for(int j=i+;j<=n;++j)
if(x[i]>x[j]) {swap(x[i],x[j]);swap(y[i],y[j]);}
else if(x[i]==x[j]&&y[i]>=y[j]) swap(y[i],y[j]); Dp(); for(int i=;i<=n;++i)
swap(x[i],y[i]); for(int i=;i<=n;++i)
for(int j=i+;j<=n;++j)
if(x[i]>x[j]) {swap(x[i],x[j]);swap(y[i],y[j]);}
else if(x[i]==x[j]&&y[i]>=y[j]) swap(y[i],y[j]); Dp(); cout<<ans<<endl;
return ; }
NOIP2002 矩形覆盖的更多相关文章
- [LuoguP1034][Noip2002] 矩形覆盖
[LuoguP1034][Noip2002] 矩形覆盖(Link) 在平面上有\(N\)个点,\(N\)不超过五十, 要求将这\(N\)个点用\(K\)个矩形覆盖,\(k\)不超过\(4\),要求最小 ...
- NOIP2002矩形覆盖[几何DFS]
题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这 ...
- 洛谷1034 NOIP2002 矩形覆盖
问题描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7). 这些点可以 ...
- COGS103&tyvj1899 [NOIP2002]矩形覆盖
题目里给的范围是k<=4,但是官方数据并没有k==4的情况,导致一些奇奇怪怪的DP写法也能过.听说标程在k==4的时候有反例,掀桌-.. 难怪COGS上k==4的数据答案是错的. 还是好好写个搜 ...
- 【OpenJudge 1793】矩形覆盖
http://noi.openjudge.cn/ch0405/1793/ 好虐的一道题啊. 看数据范围,一眼状压,然后调了好长时间QwQ 很容易想到覆盖的点数作为状态,我用状态i表示至少覆盖状态i表示 ...
- bzoj 1185 旋转卡壳 最小矩形覆盖
题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点 这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性 ...
- [剑指OFFER] 斐波那契数列- 跳台阶 变态跳台阶 矩形覆盖
跳台阶 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. class Solution { public: int jumpFloor(int number) ...
- UVA-11983-Weird Advertisement(线段树+扫描线)[求矩形覆盖K次以上的面积]
题意: 求矩形覆盖K次以上的面积 分析: k很小,可以开K颗线段树,用sum[rt][i]来保存覆盖i次的区间和,K次以上全算K次 // File Name: 11983.cpp // Author: ...
- 【旋转卡壳+凸包】BZOJ1185:[HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1945 Solve ...
随机推荐
- (转载)delphi 中如何调用sql 存储过程
delphi 中如何调用sql 存储过程 使用TADOStoredProc组件,可以,给你举个例子好了 with ADOStoredProc1 do begin Close; Parameters.C ...
- javascript debut trick, using the throw to make a interrupt(breakpoint) in your program
console.log('initialize'); try { throw "breakPoint"; } catch(err) {} when I debug the extj ...
- iOS runloop 资源汇总-b
RunLoop 是 iOS 和 OSX 开发中非常基础的一个概念,这篇文章将从 CFRunLoop 的源码入手,介绍 RunLoop 的概念以及底层实现原理.之后会介绍一下在 iOS 中,苹果是如何利 ...
- Memcache仅仅支持简单数据类型
Memcache仅仅支持简单数据类型 ,复杂数据类型需要应用自己处理 从数据库当中取出数据[User [id=1, username=guowuxin, password=guowuxin], Use ...
- Uva 654 Ratio
题意: 给两个数, n, m 构造一个序列, 分母从1 ~ m, 并且j / i越来越接近n/m. 思路: 如果存在 j / i 趋近于 n / m 那么则有 j = n * i / m + 0.5( ...
- CentOS查看CPU信息、位数、多核信息
# uname -a Linux localhost.localdomain 2.6.18-164.el5PAE #1 SMP Thu Sep 3 04:10:44 EDT 2009 i686 i68 ...
- Hex、bin、axf、elf格式文件小结
转自Hex.bin.axf.elf格式文件小结 一.HEX Hex文件,一般是指Intel标准的十六进制文件.Intelhex 文件常用来保存单片机或其他处理器的目标程序代码.它保存物理程序存储区中的 ...
- easyui源码翻译1.32--ComboBox(下拉列表框)
前言 扩展自$.fn.combo.defaults.使用$.fn.combobox.defaults重写默认值对象.下载该插件翻译源码 下拉列表框显示一个可编辑文本框和下拉式列表,用户可以选择一个值或 ...
- PDF文件结构
概述PDF是一种不依赖应用程序软件.硬件和操作系统的文件格式.PDF页包含文本.图形和图像.页面外观由内容流(content stream)描述,内容流包含一些列图形对象(graphics objec ...
- javaweb学习总结(四十)——编写自己的JDBC框架
一.元数据介绍 元数据指的是"数据库"."表"."列"的定义信息. 1.1.DataBaseMetaData元数据 Connection.g ...