【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的大矩形,总共有多少种方法? 思路:最初看到这题,只能通过画图归纳来寻找规律. ...
随机推荐
- AJAX初探,XMLHttpRequest介绍
AJAX初探,XMLHttpRequest介绍 AJAX AJAX = Asynchronous JavaScript and XML. 异步的JavaScript和XML. AJ ...
- iOS开发之功能模块--用runtime给UIView类别拓展PressMenu工具
这是个很有用的列别工具类,在聊天对话框添加和QQ一样的"复制.粘贴.取消"等选项,而且使用起来很方便,只要找到聊天泡泡内部的某个View,比如Label或者背景冒泡的UIImage ...
- 《C#高级编程》读书笔记
<C#高级编程>读书笔记 C#类型的取值范围 名称 CTS类型 说明 范围 sbyte System.SByte 8位有符号的整数 -128~127(−27−27~27−127−1) sh ...
- mysql与oracle的日期/时间函数小结
前言 本文的日期/时间全部格式化为”2016-01-01 01:01:01“形式: MONITOR_TIME为数据库表字段: 字符串与日期/时间相互转换函数 Oracle 日期/时间转字符串函数:to ...
- Linux(RHEL7.0)下安装nginx-1.10.2
查看当前系统版本是否支持 当前,nginx发布包支持以下Linux操作系统版本: RHEL/CentOS: Version Supported Platforms 5.x x86_64, i386 6 ...
- SQL SERVER 临时表导致存储过程重编译(recompile)的一些探讨
SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile).那么引发存储过程重编译的条件有哪一些呢 ...
- SQL Server 列存储索引强化
SQL Server 列存储索引强化 SQL Server 列存储索引强化 1. 概述 2.背景 2.1 索引存储 2.2 缓存和I/O 2.3 Batch处理方式 3 聚集索引 3.1 提高索引创建 ...
- [解决]Mercurial HTTP Error 500: Access is denied on 00changelog.i
总之,用户对仓库目录要有写权限 00changelog, access is denied, hg, http error 500, mercurial, permissions, push Merc ...
- 基于Simple Image Statistics(简单图像统计,SIS)的图像二值化算法。
这是个简单的算法,是全局二值算法的一种,算法执行速度快. 算法过程简单描述如下: 对于每一个像素,做如下处理 1.计算当前像素水平和垂直方向的梯度. (two gradients are calcul ...
- hibernate inverse属性的作用
hibernate配置文件中有这么一个属性inverse,它是用来指定关联的控制方的.inverse属性默认是false,若为false,则关联由自己控制,若为true,则关联由对方控制.见例子: 一 ...