zoj3209-Treasure Map
给出一个左下角为\((0,0)\),右上角为\((n,m)\)的矩形,再给出\(k\)个在大矩形内的小矩形(可以重合),问是否能用这些小矩形完全覆盖这个大矩形,并且没有重合,如果可以至少需要多少个。
分析
看到覆盖和没有重合,就可以知道是精确覆盖问题。精确覆盖问题的经典数据结构Dancing Links用来优化X算法可以很高效地解决。
精确覆盖问题的重点在于转化成DLX能够处理的01矩阵精确覆盖。这个转化的一个有效的方法就是,找到什么东西不能重合,什么东西只能覆盖一次。
例如这个题中,说的是小矩形不能重合,事实上可以转化成每个格子只能被一个矩形覆盖,并且一定要覆盖。这样问题就简单了。我们建一个01矩阵,\(k\)行\(n\times m\)列,表示一个矩形能够覆盖哪些点。这样就可以直接用Dancing Links X解01精确覆盖的方法来解决了。
代码
这道题虽然简单,但又写了差不多一天。在一些acm网站上做题总是这样,都不知道哪里错了,不小心有AC了,又不知道怎么回事,好像之前Topcoder的愚人节比赛一样。不过还是找出原因了。
一个是在给点编号的时候,写的应该是\((x-1)*m+y\),因为\(x\)是跟\(n\)有关的。还有一个就是,X算法本质上就是深搜的循环双向十字链表优化,所以该剪枝还是要剪枝,比如这里的最优性剪枝。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=5e2+100;
const int maxm=1e3+100;
const int maxp=maxm*maxn;
const int inf=1e9+7;
bool a[maxn][maxm];
int n,m,ans;
int id(int x,int y) {
return (x-1)*m+y;
}
struct node {
int l,r,u,d,row,col;
};
struct DLX {
node p[maxp];
int last[maxm],tot,size[maxm];
void clear(int cs) {
memset(last,0,sizeof last);
memset(size,0,sizeof size);
memset(p,0,sizeof p);
for (int i=1;i<=cs;++i) last[i]=i;
tot=cs;
for (int i=1;i<=cs;++i) {
p[i]=(node){i-1,p[i-1].r,i,i,0,i};
p[p[i].l].r=p[p[i].r].l=i;
}
}
void build(int row,int c[],int len) {
p[++tot]=(node){tot,tot,last[c[1]],p[last[c[1]]].d,row,c[1]};
p[p[tot].u].d=p[p[tot].d].u=last[c[1]]=tot;
++size[c[1]];
for (int i=2;i<=len;++i) {
int x=c[i];
p[++tot]=(node){tot-1,p[tot-1].r,last[x],p[last[x]].d,row,x};
p[p[tot].l].r=p[p[tot].r].l=p[p[tot].u].d=p[p[tot].d].u=last[x]=tot;
++size[x];
}
}
void del(int c) {
p[p[c].l].r=p[c].r,p[p[c].r].l=p[c].l;
for (int i=p[c].d;i!=c;i=p[i].d) for (int j=p[i].r;j!=i;j=p[j].r) p[p[j].d].u=p[j].u,p[p[j].u].d=p[j].d,--size[p[j].col];
}
void back(int c) {
p[p[c].l].r=p[p[c].r].l=c;
for (int i=p[c].u;i!=c;i=p[i].u) for (int j=p[i].l;j!=i;j=p[j].l) p[p[j].d].u=p[p[j].u].d=j,++size[p[j].col];
}
void dance(int k) {
if (!p[0].r) {
ans=min(ans,k);
return;
}
int first=p[0].r;
for (int i=p[0].r;i;i=p[i].r) if (size[i]<size[first]) first=i;
if (p[first].d==first) return;
del(first);
for (int i=p[first].d;i!=first;i=p[i].d) {
for (int j=p[i].r;j!=i;j=p[j].r) del(p[j].col);
dance(k+1);
for (int j=p[i].l;j!=i;j=p[j].l) back(p[j].col);
}
back(first);
}
} dlx;
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("my.out","w",stdout);
#endif
int T=read();
while (T--) {
n=read(),m=read(),ans=inf;
memset(a,0,sizeof a);
int K=read();
dlx.clear(n*m);
for (int k=1;k<=K;++k) {
int x1=read(),y1=read(),x2=read(),y2=read();
for (int i=x1+1;i<=x2;++i) for (int j=y1+1;j<=y2;++j) a[k][id(i,j)]=true;
}
for (int i=1;i<=K;++i) {
static int c[maxm];
int tot=0;
for (int j=1;j<=n*m;++j) if (a[i][j]) c[++tot]=j;
dlx.build(i,c,tot);
}
dlx.dance(0);
printf("%d\n",ans==inf?-1:ans);
}
return 0;
}
zoj3209-Treasure Map的更多相关文章
- ZOJ3209 Treasure Map —— Danc Links 精确覆盖
题目链接:https://vjudge.net/problem/ZOJ-3209 Treasure Map Time Limit: 2 Seconds Memory Limit: 32768 ...
- ZOJ 3209 Treasure Map (Dancing Links)
Treasure Map Time Limit: 2 Seconds Memory Limit: 32768 KB Your boss once had got many copies of ...
- ZOJ 3209 Treasure Map (Dancing Links)
Treasure Map Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Submit S ...
- (简单) ZOJ 3209 Treasure Map , DLX+精确覆盖。
Description Your boss once had got many copies of a treasure map. Unfortunately, all the copies are ...
- ZOJ 3209 Treasure Map(精确覆盖)
Treasure Map Time Limit: 2 Seconds Memory Limit: 32768 KB Your boss once had got many copies of ...
- 2017年上海金马五校程序设计竞赛:Problem K : Treasure Map (蛇形填数)
Description There is a robot, its task is to bury treasures in order on a N × M grids map, and each ...
- ZOJ 3209 Treasure Map DLX
用最少的矩阵覆盖n*m的地图.注意矩阵不能互相覆盖. 这里显然是一个精确覆盖,但因为矩阵拼接过程中,有公共的边,这里须要的技巧就是把矩阵的左边和以下截去一个单位. #include <stdio ...
- zoj 3209.Treasure Map(DLX精确覆盖)
直接精确覆盖 开始逐行添加超时了,换成了单点添加 #include <iostream> #include <cstring> #include <cstdio> ...
- ZOJ 3209 Treasure Map 精确覆盖
题目链接 精确覆盖的模板题, 把每一个格子当成一列就可以. S忘记初始化TLE N次, 哭晕在厕所...... #include<bits/stdc++.h> using namespac ...
- zoj - 3209 - Treasure Map(精确覆盖DLX)
题意:一个 n x m 的矩形(1 <= n, m <= 30),现给出这个矩形中 p 个(1 <= p <= 500)子矩形的左下角与右下角坐标,问最少用多少个子矩形能够恰好 ...
随机推荐
- 20145202马超 2016-2017-2 《Java程序设计》第二次实验
去年完成的一部分(http://www.cnblogs.com/tuolemi/p/5728826.html) 今年我又从新做的,这是分别5个问题做出来的结果 下面这个是去年没有做的,是用来建模的,感 ...
- 记录:C#监视某个文件的打开记录
首先,先说下为什么要搞这个: 1.首先,我的电脑里有5万左右的目录或文件,用于存放歌曲,数量众多.2.我不一定会用哪种软件听歌(不过也就是几种而已).3.我想在听歌的时候,检测哪首首歌被打开,能获取到 ...
- 关于C++虚函数表的那些事儿
前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛 ...
- XSS--编码绕过,qcms,鲶鱼cms
一.编码绕过 1)HTML进制编码 标签中的某些属性值可以使用html十进制.十六进制表示 2)JavaScript编码 JavaScript支持unicode.八进制.十六进制.十进制等 3)URL ...
- unittest,selenium——批量,多线程执行多文档用例
之前做过批量执行多.py文件,为了省时也做过单py文件多线程,现在做多py文件用例多线程 # coding:utf-8import unittestimport osimport timeimport ...
- Python 多线程、进程、协程上手体验
浅谈 Python 多线程.进程.协程上手体验 前言:浅谈 Python 很多人都认为 Python 的多线程是垃圾(GIL 说这锅甩不掉啊~):本章节主要给你体验下 Python 的两个库 Thre ...
- Unity编辑器 - 资源修改立即写入磁盘AssetDataBase.SaveAssets()
Unity编辑器 - 资源修改立即写入磁盘AssetDataBase.SaveAssets() 在编写编辑器时,如果需要修改Unity序列化资源(如Prefab,美术资源,ScriptableObje ...
- Python 的非正式介绍
在下面的例子中,通过提示符 (>>> 与 ...) 的出现与否来区分输入和输出:如果你想复现这些例子,当提示符出现后,你必须在提示符后键入例子中的每一个词:不以提示符开头的那些行是解 ...
- [JSON].valueOf( keyPath )
语法:[JSON].valueOf( keyPath ) 返回:[任意类型 | null] 说明:获取键名路径原值,它保留原始值的类型 示例: b = sysFile.binary("tes ...
- (转)GEM -次表面散射的实时近似
次表面散射(Subsurface Scattering),简称SSS,或3S,是光射入非金属材质后在内部发生散射, 最后射出物体并进入视野中产生的现象, 即光从表面进入物体经过内部散射,然后又通过物体 ...