题意 :  给你一个大小为 n * m 的矩形 , 坐标是( 0 , 0 ) ~ ( n , m )  。然后给你 p 个小矩形 。 坐标是( x1 , y1 ) ~ ( x2 , y2 ) , 你选择最小的几个矩形 , 使得这些矩形能够覆盖整个矩形 。 而且互相不会重叠 。( n , m <= 30 )

思路 : Dancing Links 的精确覆盖问题 。

我们将 n * m 的矩形分成 n * m 个小正方形 ,那么我们仅仅要保证每一个小正方形被覆盖且仅仅被覆盖一次就可以 。

那么列表示每一个小正方形 。 行表示你选择的矩形 。 假设选择这个矩形能够覆盖某个小正方形 。 则相应的格子是1 , 否则相应的格子是 0

最多有 30 * 30 = 900 列 ,最多有 500 行

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std; const int maxn = 900 + 10 ;
const int maxr = 500 + 10 ;
const int maxnode = 500 * 900 + maxr + 10 ; #define FOR( i , A , s ) for( int i = A[s] ; i != s ; i = A[i] ) struct DLX{
// maxn 列数 , maxnode 总节点数 , maxr 行数
int n , sz ;
int S[maxn] ; int row[maxnode] , col[maxnode] ;
int L[maxnode] , R[maxnode] , U[maxnode] , D[maxnode] ;
int H[maxr] ; int ansd , ans[maxr] ; void init( int N ) {
n = N ;
// 第一行的虚拟结点
for( int i = 0 ; i <= n ; i ++ ) {
U[i] = D[i] = i ;
L[i] = i - 1 ;
R[i] = i + 1 ;
}
R[n] = 0 ; L[0] = n ;
sz = n + 1 ;
// 每一列的个数
memset( S , 0 , sizeof(S) ) ;
// H[i] = -1 表示这一行还没有 1
// 否则表示第一个 1 的 sz 是多少
memset( H , -1 , sizeof(H)) ;
} // 在第r行第c列加入一个1
void Link( int r , int c ) {
row[sz] = r ;
col[sz] = c ;
S[c] ++ ; D[sz] = c ; U[sz] = U[c] ;
D[U[c]] = sz ; U[c] = sz ; if( H[r] < 0 ) { H[r] = L[sz] = R[sz] = sz ; }
else{
R[sz] = H[r] ;
L[sz] = L[H[r]] ;
R[L[sz]] = sz ;
L[R[sz]] = sz ;
} sz ++ ; } // 删除 第 c 列
void remove ( int c ) {
// 删除虚拟结点中的 c 列
L[R[c]] = L[c] ;
R[L[c]] = R[c] ;
// 从 c 列向下遍历
FOR( i , D , c ) {
// 删除遍历到的行
FOR( j , R , i ) {
D[U[j]] = D[j] ;
U[D[j]] = U[j] ;
-- S[col[j]] ;
}
}
} // 恢复第 c 列
void restore( int c ) {
FOR( i , U , c ) {
FOR( j , L , i ) {
++S[col[j]] ;
U[D[j]] = D[U[j]] = j ;
}
}
L[R[c]] = R[L[c]] = c ;
} void dfs( int d ) { // 剪枝
if( d >= best ) {
return ;
} // R[0] = 0 表示找到一个可行解
if( R[0] == 0 ) {
best = d ;
return ;
} // 找到 s 最小的列 , 加快搜索的速度
int c = R[0] ;
FOR( i , R , 0 )
if( S[i] < S[c] ) c = i ; // 删除第 c 列
remove( c ) ; // 遍历选中列中有1的行
FOR( i , D , c ) {
ans[d] = row[i] ;
// 删除选中行中有1的列
FOR( j , R , i ) {
remove( col[j] ) ;
}
dfs( d + 1 ) ;
// 回复删除掉的列
FOR( j , L , i ) {
restore( col[j] ) ;
}
}
restore( c ) ;
} int solve() {
best = INF ;
dfs( 0 ) ;
if( best == INF )
return -1 ;
else
return best ;
}
int best ;
const static int INF = 0x3f3f3f3f ;
} dlx ; int main(){
int cas ;
scanf( "%d" , &cas ) ;
while( cas -- ) {
int n , m , p ;
scanf( "%d%d%d" , &n , &m , &p ) ;
dlx.init( n * m ) ;
for( int i = 1 ; i <= p ; i ++ ) {
int x1 , y1 , x2 , y2 ;
scanf( "%d%d%d%d" , &x1 , &y1 , &x2 , &y2 ) ;
for( int x = x1 ; x < x2 ; x ++ ) {
for( int y = y1 ; y < y2 ; y ++ ) {
dlx.Link( i , x * m + y + 1 ) ;
}
}
}
printf( "%d\n" , dlx.solve() ) ;
}
return 0 ;
}

ZOJ 3209 Treasure Map (Dancing Links 精确覆盖 )的更多相关文章

  1. ZOJ 3209 Treasure Map (Dancing Links)

    Treasure Map Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit S ...

  2. zoj 3209.Treasure Map(DLX精确覆盖)

    直接精确覆盖 开始逐行添加超时了,换成了单点添加 #include <iostream> #include <cstring> #include <cstdio> ...

  3. ZOJ3209 Treasure Map —— Danc Links 精确覆盖

    题目链接:https://vjudge.net/problem/ZOJ-3209 Treasure Map Time Limit: 2 Seconds      Memory Limit: 32768 ...

  4. ZOJ 3209 Treasure Map (Dancing Links)

    Treasure Map Time Limit: 2 Seconds      Memory Limit: 32768 KB Your boss once had got many copies of ...

  5. ZOJ 3209 Treasure Map(精确覆盖)

    Treasure Map Time Limit: 2 Seconds      Memory Limit: 32768 KB Your boss once had got many copies of ...

  6. (简单) ZOJ 3209 Treasure Map , DLX+精确覆盖。

    Description Your boss once had got many copies of a treasure map. Unfortunately, all the copies are ...

  7. ZOJ 3209 Treasure Map 精确覆盖

    题目链接 精确覆盖的模板题, 把每一个格子当成一列就可以. S忘记初始化TLE N次, 哭晕在厕所...... #include<bits/stdc++.h> using namespac ...

  8. zoj - 3209 - Treasure Map(精确覆盖DLX)

    题意:一个 n x m 的矩形(1 <= n, m <= 30),现给出这个矩形中 p 个(1 <= p <= 500)子矩形的左下角与右下角坐标,问最少用多少个子矩形能够恰好 ...

  9. hihoCoder #1321 : 搜索五•数独 (Dancing Links ,精确覆盖)

    hiho一下第102周的题目. 原题地址:http://hihocoder.com/problemset/problem/1321 题意:输入一个9*9数独矩阵,0表示没填的空位,输出这个数独的答案. ...

随机推荐

  1. IBatis的分页研究

    IBatis的分页研究 博客分类: Ibatis学习   摘自: http://cpu.iteye.com/blog/311395 yangtingkun   Oracle分页查询语句 ibaits. ...

  2. LDA主题模型(理解篇)

    何谓“主题”呢?望文生义就知道是什么意思了,就是诸如一篇文章.一段话.一个句子所表达的中心思想.不过从统计模型的角度来说, 我们是用一个特定的词频分布来刻画主题的,并认为一篇文章.一段话.一个句子是从 ...

  3. vim之vimrc配置文件

    """"""""""""""""&quo ...

  4. C++_运算符重载 总结

    什么是运算符的重载? 运算符与类结合,产生新的含义. 为什么要引入运算符重载? 作用:为了实现类的多态性(多态是指一个函数名有多种含义) 怎么实现运算符的重载? 方式:类的成员函数 或 友元函数(类外 ...

  5. 如何在mybatis中引用java中的常量和方法

    转自:http://www.68idc.cn/help/jiabenmake/qita/20140821125261.html 在mybatis的映射xml文件调用java类的方法: 1. SELEC ...

  6. 习题练习(视觉slam14讲课后习题)

    设有⼩萝⼘1⼀号和⼩萝⼘⼆号位于世界坐标系中. ⼩萝⼘⼀号的位姿为:q1 = [0.55, 0.3, 0.2, 0.2], t1 = [0.7, 1.1, 0.2]T(q 的第⼀项为实部).这⾥的 q ...

  7. Python学会之后,一般能拿到多少工资?

    Python在约40年前出现以来,已经有数以千计基于这项技术的网站和软件项目,Python因其独有的特点从众多开发语言中脱颖而出,深受世界各地的开发者喜爱. 随着Python的技术的流行,Python ...

  8. 模板—treap

    #include<iostream> #include<cstdio> #include<cstdlib> #define INF 0x7fffffff using ...

  9. html option选中 回显 取值

    1.html <select class="form-control" id="sex"> <option value="-1&qu ...

  10. Python学习第二阶段day1 内置函数,序列化,软件目录开发规范

    内置函数 1.abs()  求绝对值 2.all()    所有元素为真才返回真 all( [1,1,2,3,-1] ) 值为True 3.any()   所有元素为假才返回假  any([0,0,0 ...