ZOJ3209 Treasure Map —— Danc Links 精确覆盖
题目链接:https://vjudge.net/problem/ZOJ-3209
Treasure Map
Time Limit: 2 Seconds Memory Limit: 32768 KB
Your boss once had got many copies of a treasure map. Unfortunately, all the copies are now broken to many rectangular pieces, and what make it worse, he has lost some of the pieces.
Luckily, it is possible to figure out the position of each piece in the original map. Now the boss asks you, the talent programmer, to make a complete treasure map with these pieces. You need to make only one complete map and it is not necessary to use all
the pieces. But remember, pieces are not allowed to overlap with each other (See sample 2).
Input
The first line of the input contains an integer T (T <= 500), indicating the number of cases.
For each case, the first line contains three integers n m p (1 <= n, m <= 30, 1 <= p <= 500), the width and the height of the map, and the number of
pieces. Then p lines follow, each consists of four integers x1 y1 x2 y2 (0 <= x1 < x2 <= n, 0 <= y1 < y2 <= m), where (x1, y1) is the coordinate of the lower-left corner of the rectangular
piece, and (x2, y2) is the coordinate of the upper-right corner in the original map.
Cases are separated by one blank line.

Output
If you can make a complete map with these pieces, output the least number of pieces you need to achieve this. If it is impossible to make one complete map, just output -1.
Sample Input
3
5 5 1
0 0 5 5 5 5 2
0 0 3 5
2 0 5 5 30 30 5
0 0 30 10
0 10 30 20
0 20 30 30
0 0 15 30
15 0 30 30
Sample Output
1
-1
2
Hint
For sample 1, the only piece is a complete map.
For sample 2, the two pieces may overlap with each other, so you can not make a complete treasure map.
For sample 3, you can make a map by either use the first 3 pieces or the last 2 pieces, and the latter approach one needs less pieces.
题解:
题意:有p个矩形,每个矩形的坐标均已知,问能否找到若干个矩形(不能有重叠),组成一个n*m的大矩形?如果能?找出最小值。
两个注意点:
1.一开始以为覆盖的对象是“点”,结果发现在拼接处会重复覆盖。后来才知道覆盖的对象是一个“小格”,即单位正方形。这样才是以面积覆盖掉n*m的大矩形。代码中以(x,y)这个点代表了((x-1,y-1) (x,y))这个单位正方形,所以这个大矩形的横纵坐标从1开始。
2.在写Dance()函数时,忘了修改代码。由于此题要求求出最小值,所以即使当前找到某个值,也不一定是最小值,还要继续回溯。所以Dance()函数的类型是 void, 而不是bool。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long LL;
const int INF = 2e9;
const int MAXN = 1e3+10;
const int MAXM = 1e3+10;
const int maxnode = 1e6+10; struct DLX //矩阵的行和列是从1开始的
{
int n, m, size; //size为结点数
int U[maxnode], D[maxnode], L[maxnode], R[maxnode], Row[maxnode], Col[maxnode];
int H[MAXN], S[MAXM]; //H为每一行的头结点,但不参与循环。S为每一列的结点个数
int ansd; void init(int _n, int _m) //m为列
{
n = _n;
m = _m;
for(int i = 0; i<=m; i++) //初始化列的头结点
{
S[i] = 0;
U[i] = D[i] = i;
L[i] = i-1;
R[i] = i+1;
}
R[m] = 0; L[0] = m;
size = m;
for(int i = 1; i<=n; i++) H[i] = -1; //初始化行的头结点
} void Link(int r, int c)
{
size++; //类似于前向星
Col[size] = c;
Row[size] = r;
S[Col[size]]++;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if(H[r]==-1) H[r] = L[size] = R[size] = size; //当前行为空
else //当前行不为空: 头插法,无所谓顺序,因为Row、Col已经记录了位置
{
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
} void remove(int c) //c是列的编号, 不是结点的编号
{
L[R[c]] = L[c]; R[L[c]] = R[c]; //在列的头结点的循环队列中, 越过列c
for(int i = D[c]; i!=c; i = D[i])
for(int j = R[i]; j!=i; j = R[j])
{
//被删除结点的上下结点仍然有记录
U[D[j]] = U[j];
D[U[j]] = D[j];
S[Col[j]]--;
}
} void resume(int c)
{
L[R[c]] = R[L[c]] = c;
for(int i = U[c]; i!=c; i = U[i])
for(int j = L[i]; j!=i; j = L[j])
{
U[D[j]] = D[U[j]] = j;
S[Col[j]]++;
}
} void Dance(int d)
{
if(d>=ansd) return;
if(R[0]==0)
{
ansd = d;
return;
} int c = R[0];
for(int i = R[0]; i!=0; i = R[i]) //挑结点数最少的那一列,否则会超时,那为什么呢?
if(S[i]<S[c])
c = i; remove(c);
for(int i = D[c]; i!=c; i = D[i])
{
for(int j = R[i]; j!=i; j = R[j]) remove(Col[j]);
Dance(d+1);
for(int j = L[i]; j!=i; j = L[j]) resume(Col[j]);
}
resume(c);
}
}; DLX dlx;
int main()
{
int T;
int n, m, p;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &n, &m, &p);
dlx.init(p, n*m);
for(int i = 1; i<=p; i++)
{
int x1, x2, y1, y2;
scanf("%d%d%d%d",&x1, &y1, &x2, &y2);
for(int x = x1+1; x<=x2; x++)
for(int y = y1+1; y<=y2; y++)
dlx.Link(i, (x-1)*m+y);
}
dlx.ansd = INF;
dlx.Dance(0);
printf("%d\n", dlx.ansd==INF?-1:dlx.ansd);
}
return 0;
}
ZOJ3209 Treasure Map —— Danc Links 精确覆盖的更多相关文章
- zoj 3209.Treasure Map(DLX精确覆盖)
直接精确覆盖 开始逐行添加超时了,换成了单点添加 #include <iostream> #include <cstring> #include <cstdio> ...
- ZOJ 3209 Treasure Map (Dancing Links 精确覆盖 )
题意 : 给你一个大小为 n * m 的矩形 , 坐标是( 0 , 0 ) ~ ( n , m ) .然后给你 p 个小矩形 . 坐标是( x1 , y1 ) ~ ( x2 , y2 ) , 你选 ...
- hihoCoder #1321 : 搜索五•数独 (Dancing Links ,精确覆盖)
hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. ...
- 【转】Dancing Links精确覆盖问题
原文链接:http://sqybi.com/works/dlxcn/ (只转载过来一部分,全文请看原文,感觉讲得很好~)正文 精确覆盖问题 解决精确覆盖问题 舞蹈步骤 效率分析 ...
- hust 1017 dancing links 精确覆盖模板题
最基础的dancing links的精确覆盖题目 #include <iostream> #include <cstring> #include <cstdio> ...
- ZOJ 3209 Treasure Map (Dancing Links)
Treasure Map Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Submit S ...
- HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )
推荐两篇学DLX的博文: http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细) http://yzmduncan.iteye.co ...
- POJ3074 Sudoku —— Dancing Links 精确覆盖
题目链接:http://poj.org/problem?id=3074 Sudoku Time Limit: 1000MS Memory Limit: 65536K Total Submissio ...
- HUST1017 Exact cover —— Dancing Links 精确覆盖 模板题
题目链接:https://vjudge.net/problem/HUST-1017 1017 - Exact cover 时间限制:15秒 内存限制:128兆 自定评测 7673 次提交 3898 次 ...
随机推荐
- 【Git】Git 本地的撤销修改和删除操作
一:撤销操作 比如我现在在readme.txt文件里面增加一行 内容为555555555555,我们先通过命令查看如下: 在我未提交之前,我发现添加5555555555555内容有误,所以我得马上恢复 ...
- C++ assert 的一点说明
断言(ASSERT)的用法 转载自http://www.cnblogs.com/moondark/archive/2012/03/12/2392315.html 我一直以为assert仅仅是个报错函数 ...
- android layout
android的视图分为两类,一类是布局,另一个类是控件 一.LinearLayout(线性布局) 最常用布局之一,线性布局的特性是每添加一个控件默认会在上个控件的下面占一行. <LinearL ...
- Codeforces 959 D Mahmoud and Ehab and another array construction task
Discription Mahmoud has an array a consisting of n integers. He asked Ehab to find another arrayb of ...
- JS实现根据密码长度 显示安全条
原文:http://www.open-open.com/code/view/1431324883763 //根据密码长度显示安全条 <ul class="clear"> ...
- 实践与理解CMM体系
我的项目管理之路--5.实践与理解CMM体系 分类: 管理专辑(65) 过程改进(9) 软件工程(52) 版权声明:本文为博主原创文章,未经博主允许不得转载. 一个现代企业我们可以把它比作为自然界 ...
- 用 centrifugo 搭建 消息推送服务器 docker + rancher 搭建
关于消息推送服务器 目前有很多第三方的开放成熟的推送服务.鉴于项目需要 我们项目需要自己搭建 自己的推送服务. 我们的推送应用场景 聊天消息 项目内部消息提醒 移动设备接受消息 应用到的相关软件工具知 ...
- Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制
转自:xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/21696315) 今天这篇文章主要分析的是Android的事件分发机制, ...
- MFC Month Calendar Control 控件使用
在上层软件编程中,往往须要提供一个月历控件让用户选择对应日期或者用此月历控件来强调特定的一天. MFC的 Month Calendar Control 控件自系统升级到 Windows 7 之后,对于 ...
- unity常见问题之20题
1:天空盒有接缝怎么解决? 答:在贴图导入设置里设置Wrap Mode为"Clamp". 2: DDS格式怎么不显示? 答:Unity不支持DDS格式,Unity会将除DDS外的其 ...