【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的大矩形,总共有多少种方法? 思路:最初看到这题,只能通过画图归纳来寻找规律. ...
随机推荐
- 关于Hibernate 的数据库配置
<hibernate-configuration> <session-factory name="mySessionFactory"> ...
- iPhone 丢失
http://www.appvv.com/zhuanti/iccid/ 第一步:iPhone丢失后,及时报警,在最短时间内补办SIM卡或把卡停掉. 第二步:输入查询网址:sn.appvv.com 输入 ...
- JS实现HTML标签转义及反转义
今天我用ueditor时候遇到一个问题: 我从数据库中读取内容进行编辑的时候,不是有一些html标签嘛,从数据库读出来没有问题: 但是我用asp.net mvc,把读取出来的内容通过ueditor的a ...
- IP 地址分类(A、B、C、D、E类)
互联网上的接口的唯一地址. IP 32位的地址通常表示为四个10进制的数,每个证书对应一个字节,成为点分十进制法(Dotted decimal notation) 如上图首字节整数:A类--0开始,B ...
- W3School-CSS 定位 (Positioning) 实例
CSS 定位 (Positioning) 实例 CSS 实例 CSS 背景实例 CSS 文本实例 CSS 字体(font)实例 CSS 边框(border)实例 CSS 外边距 (margin) 实例 ...
- 【转】用C写一个简单病毒
[摘要]在分析病毒机理的基础上,用C语言写了一个小病毒作为实例,用TURBOC2.0实现. [Abstract] This paper introduce the charateristic of t ...
- 解决UDT中内存下不去的问题
使用UDT库,编写简单的网络通信程序,发现了一个问题,关闭一部分连接后,程序占用内存并没有变化. 比如先连接500个,再连接另500个,先关掉后面500个,程序占用内存降一半,再关 ...
- android Dialog实例
Dialog类 public class DialogUtil { public static Dialog EditDialog(Activity context,View view){ final ...
- asp.net设置默认打开页面,Web.config,defaultDocument
The web.config file can be used to set a default document, or list of default documents for your web ...
- linux 文件系统结构及命令
1.linux 文件系统结构 / 根目录 root |--mnt/ | |--sdcard/ 挂载点 | |--usb0 | |--cdrom |--home | |--soft01 <- 用 ...