【OpenJudge 1793】矩形覆盖
http://noi.openjudge.cn/ch0405/1793/
好虐的一道题啊。
看数据范围,一眼状压,然后调了好长时间QwQ
很容易想到覆盖的点数作为状态,我用状态i表示至少覆盖状态i表示的点的最小矩形覆盖面积。
又因为矩形一定在两个给出的点上,转移时枚举两个点,用去掉这两个点的状态来更新?
这是错误的做法,反例:4 (0,0) (0,1) (1,0) (1,1)
所以我们需要去掉这两个点的同时,去掉这两个点构成的矩形包含的所有在状态中的点。
但这样还是会WA,因为还需要初始化至少包含一个点(状态中有一个点)的矩形覆盖,只要找和这个点和其他点构成的最小矩形面积就可以了。
这样还要注意,如果计算至少包含两个点的状态(状态中有两个点),最小矩形不一定是这两个点构成的矩形,有可能是这两个点分别和其他点构成的矩形。
所以转移时除了枚举两个点构成的矩形,还要枚举去掉一个点的状态和去掉的这个点的状态来转移,防止状态包含的这些点的最小矩形覆盖没有一个同时覆盖了状态中的两个点。
(如果转移时枚举的两个点的横坐标(或纵坐标)相同,需要分向左向右(或向上向下)两种情况来转移)
提供一组数据(答案为17):
8
2 10
2 7
9 3
2 4
0 7
1 0
3 0
5 5
0
时间复杂度\(O(2^nn^3)\)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = k * 10 + c - 48;
return k * fh;
}
int sum[20][20], f[40000], n, x[20], y[20], tot, id[20], cnt, a, b, from, h, l, X0, X1, Y0, Y1;
int main() {
while (n = in()) {
memset(f, 60, sizeof(f));
f[0] = 0;
for(int i = 0; i < n; ++i)
x[i] = in(), y[i] = in();
for(int i = 0; i < n; ++i)
for(int j = i + 1; j < n; ++j) {
if (i == j) sum[i][j] = 0;
h = abs(x[i] - x[j]);
l = abs(y[i] - y[j]);
if (!h) h = 1;
if (!l) l = 1;
sum[i][j] = sum[j][i] = h * l;
}//预处理
for(int i = 0; i < n; ++i) {
tot = (1 << i);
for(int j = 0; j < n; ++j)
if (i != j)
f[tot] = min(f[tot], sum[i][j]);
}//预处理只有一个点
tot = 1 << n;
for(int i = 1; i < tot; ++i) {
cnt = 0;
for(int j = 0; j < n; ++j)
if ((1 << j) & i) {
id[++cnt] = j;
f[i] = min(f[i], f[i ^ (1 << j)] + f[1 << j]);//枚举去掉一个点的状态和去掉的这个点的状态,防止状态包含的这些点的最小矩形覆盖没有一个同时覆盖了状态中的两个点
}
for(int j = 1; j < cnt; ++j) {
a = id[j];
for(int k = j + 1; k <= cnt; ++k) {
b = id[k];
from = i;
if (x[a] < x[b]) {X0 = x[a]; X1 = x[b];}
else {X0 = x[b]; X1 = x[a];}
if (y[a] < y[b]) {Y0 = y[a]; Y1 = y[b];}
else {Y0 = y[b]; Y1 = y[a];}
if (X0 == X1) {//分向左向右
++X1;
for(int l = 1; l <= cnt; ++l)
if (X0 <= x[id[l]] && x[id[l]] <= X1 && Y0 <= y[id[l]] && y[id[l]] <= Y1)
from ^= (1 << id[l]);
f[i] = min(f[i], f[from] + sum[a][b]);
--X1; --X0;
from = i;
for(int l = 1; l <= cnt; ++l)
if (X0 <= x[id[l]] && x[id[l]] <= X1 && Y0 <= y[id[l]] && y[id[l]] <= Y1)
from ^= (1 << id[l]);
f[i] = min(f[i], f[from] + sum[a][b]);
} else if (Y0 == Y1) {//分向上向下
++Y1;
for(int l = 1; l <= cnt; ++l)
if (X0 <= x[id[l]] && x[id[l]] <= X1 && Y0 <= y[id[l]] && y[id[l]] <= Y1)
from ^= (1 << id[l]);
f[i] = min(f[i], f[from] + sum[a][b]);
--Y1; --Y0;
from = i;
for(int l = 1; l <= cnt; ++l)
if (X0 <= x[id[l]] && x[id[l]] <= X1 && Y0 <= y[id[l]] && y[id[l]] <= Y1)
from ^= (1 << id[l]);
f[i] = min(f[i], f[from] + sum[a][b]);
} else {
for(int l = 1; l <= cnt; ++l)
if (X0 <= x[id[l]] && x[id[l]] <= X1 && Y0 <= y[id[l]] && y[id[l]] <= Y1)
from ^= (1 << id[l]);
f[i] = min(f[i], f[from] + sum[a][b]);
}
}
}
}
printf("%d\n", f[tot - 1]);
}
return 0;
}
一年前WA的题现在才A。。。
【OpenJudge 1793】矩形覆盖的更多相关文章
- NOIP2002矩形覆盖[几何DFS]
题目描述 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一. 这 ...
- bzoj 1185 旋转卡壳 最小矩形覆盖
题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点 这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性 ...
- [剑指OFFER] 斐波那契数列- 跳台阶 变态跳台阶 矩形覆盖
跳台阶 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. class Solution { public: int jumpFloor(int number) ...
- NOIP2002 矩形覆盖
题四 矩形覆盖(存盘名NOIPG4) [问题描述]: 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2), ...
- 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 ...
- BZOJ:1185: [HNOI2007]最小矩形覆盖
1185: [HNOI2007]最小矩形覆盖 这计算几何……果然很烦…… 发现自己不会旋转卡壳,补了下,然后发现求凸包也不会…… 凸包:找一个最左下的点,其他点按照与它连边的夹角排序,然后维护一个栈用 ...
- BZOJ 1185: [HNOI2007]最小矩形覆盖 [旋转卡壳]
1185: [HNOI2007]最小矩形覆盖 Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1435 Solve ...
- 矩形覆盖(JAVA)
矩形覆盖 题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 思路:最初看到这题,只能通过画图归纳来寻找规律. ...
随机推荐
- 参加了iDOF2016会议,发表演讲“油田SOA与云平台的系统思考与实践”
PPT的全部抓图,扫描二维码直接到微信里去看吧:
- synthesize 与dynamic的区别
官方文档解释: @synthesize will generate getter and setter methods for your property. @dynamic just tells t ...
- iOS __block 与 __weak
关于__block 与__weak http://stackoverflow.com/questions/19227982/using-block-and-weak 一下是一些区别的介绍 MRC: _ ...
- OC load与initialize
OC load与initialize load 当类被引用进程序的时候会执行这个函数 一个类的load方法不用写明[super load],父类就会收到调用,并且在子类之前. Category的loa ...
- CSS background-color 、image 背景图片
背景颜色 background-color 语法: background-color:<color> 默认值:transparent 透明 适用于:所有元素 继承性:无 动画性:是 计算 ...
- CLR简介(一)
什么是通用语言运行时(CLR),简单来讲: CLR是一个支持多种编程语言及多语言互操作,完整的高级虚拟机. 有点拗口,而且不是很有启发性,但上面的文字是将又大又复杂的CLR的功能归类以便容易理解的第一 ...
- Linux Bond 技术学习资料
Bond 技术原理 Bond 就是将多块网卡虚拟成为一块网卡的技术,通过 bond 技术让多块网卡看起来是一个单独的以太网接口设备并具有相同的 IP 地址. Bond 的原理是网卡在混杂 (promi ...
- 从零自学Hadoop(12):Hadoop命令中
阅读目录 序 HDFS Commands User Commands Administration Commands Debug Commands 引用 系列索引 本文版权归mephisto和博客园共 ...
- Echarts 之二——地市联动数据统计
一.简介 通过地图可以更直观地展示各个地区的统计数据,能够更清楚地进行数据分析.有些场景下,我们不仅仅需要对每个地市进行统计分析.更需要对地市一下的区县进行数据统计,并进行联动.此事我们可以通过Ech ...
- logback配置详解1
一:根节点<configuration>包含的属性: scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true. scanPeriod: 设置监测配置文 ...