zoj 3209 Treasure Map dancing links

来源:互联网 发布:c语言 void 编辑:程序博客网 时间:2024/06/06 08:55

题意:在给定的矩形中,选取最少的矩形数量,使之给定的能覆盖(n*m)矩形


思路:我们把题目给的q个矩形,对与每一个矩形,划分成1*1的小矩形,面积为a*b的矩形就能划分成a*b个(1*1)的小矩形,(n*m)矩形看成所有的列,每一个给定的矩形都看成行,那么就是一个精确覆盖问题。直接上白书模板,还有些小细节,看代码


题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3372



#include <cstdio>#include <cstring>#include <vector>#include <algorithm>using namespace std;const int maxn = 30 * 30;const int maxnode = 500010;const int maxr = 505;struct DLX{int n, sz;int s[maxn];int row[maxnode], col[maxnode];int l[maxnode], r[maxnode], d[maxnode], u[maxnode];int ansd, ans[maxr];void init(int n){this->n = n;for (int i = 0; i <= n; i++){u[i] = i, d[i] = i, l[i] = i - 1, r[i] = i + 1;}r[n] = 0, l[0] = n;sz = n + 1;ansd = -1;memset(s, 0, sizeof(s));}void addrow(int R, vector<int> column){int first = sz;for (int i = 0; i < (int)column.size(); i++){int c = column[i];l[sz] = sz - 1, r[sz] = sz + 1, d[sz] = c, u[sz] = u[c];d[u[c]] = sz, u[c] = sz;row[sz] = R, col[sz] = c;sz++, s[c]++;}r[sz - 1] = first, l[first] = sz - 1;}void Remove(int c){l[r[c]] = l[c];r[l[c]] = r[c];for (int i = d[c]; i != c; i = d[i]){for (int j = l[i]; j != i; j = l[j]){u[d[j]] = u[j];d[u[j]] = d[j];--s[col[j]];}}}void Restore(int c){for (int i = u[c]; i != c; i = u[i]){for (int j = r[i]; j != i; j = r[j]){++s[col[j]];d[u[j]] = j;u[d[j]] = j;}}l[r[c]] = c;r[l[c]] = c;}void dfs(int dep){    if(ansd!=-1 && ansd<dep) return ;if (r[0] == 0){    if(ansd == -1) ansd=dep;else if(ansd > dep) ansd=dep;//这里不能只搜一次,因为要找到最少的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]){ans[dep] = row[i];for (int j = r[i]; j != i; j = r[j])Remove(col[j]);            dfs(dep+1);for (int j = l[i]; j != i; j = l[j])Restore(col[j]);}Restore(c);}void solve(){    dfs(0);printf("%d\n",ansd);}};DLX dlx;int main(){int t, n, m, p;scanf("%d", &t);while (t--){scanf("%d%d%d", &n, &m, &p);int x1, y1, x2, y2;dlx.init(n*m);vector<int> v;for (int k = 1; k <= p; k++){scanf("%d%d%d%d", &x1, &y1, &x2, &y2);v.clear();for (int i = x1+1; i <= x2; i++)//这里统计的是每个矩形的格子个数,所以起始位置要+1,{for (int j = y1+1; j <= y2; j++)v.push_back((i-1)*m + j);//这里是(i-1),有些代码可能是i,这就跟编码方式有关,}dlx.addrow(k,v);}dlx.solve();}return 0;}


0 0
原创粉丝点击