POJ 1084 Square Destroyer (重复覆盖,DLX)

题目:

http://poj.org/problem?id=1084

 

题意:

给你一个n*n(n<=5)的完全由火柴棍组成的正方形,已经去掉了一些火柴棍,问最少去掉多少根火柴棍使得所有1*1、2*2......n*n的正方形均被破坏掉?

 

方法:

转换为重复覆盖问题,用DLX直接解决

1、精确覆盖与重复覆盖:《DLX在搜索中的应用》

http://bbs.whu.edu.cn/wForum/elite.php?file=%2Fgroups%2FGROUP_3%2FACM_ICPC%2Fnx08%2FD.08010000%2FM.1215524645.R0&ap=563

2、转换方法:矩阵的一行代表一根火柴棍,矩阵的一列代表一个正方形,即转换位矩阵重复覆盖问题

3、处理去掉的火柴棍:

(a)先计算不去掉火柴棍的矩阵,给火柴棍和矩阵编上号手推一下就发现规律了,我的编号和建立矩阵的方法:

 1 void calmtx()
 2 {
 3     row = 2 * n * (n + 1);
 4     col = 0;
 5     for (int i = 1; i <= n; i++)
 6         col += i * i;
 7 
 8     int cnt = 1;
 9     for (int si = 1; si <= n; si++)
10     {
11         for (int i = 1; i <= n - si + 1; i++)
12         {
13             for (int j = 1; j <= n - si + 1; j++)
14             {
15                 for (int k = 0; k < si; k++)
16                 {
17                     mtx[(i - 1) * (2 * n + 1) + j + k][cnt] = 1;
18                     mtx[(i - 1 + si) * (2 * n + 1) + j + k][cnt] = 1;
19                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1)][cnt] = 1;
20                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1) + si][cnt] = 1;
21                 }
22                 cnt++;
23             }
24         }
25     }
26 }

(b)去掉火柴棍:对去掉的火柴棍对应的正方形加标记并在DLX里面标记它们已经访问过,然后在添加link时忽略这些标记过的正方形

 1 void build()
 2 {
 3     calmtx();
 4 
 5     dlx.initL(col);
 6     for (int i = 0; i < vec.size(); i++)
 7     {
 8         int x = vec[i];
 9         for (int j = 1; j <= col; j++)
10             if (mtx[x][j] && !vis[j])
11             {
12                 vis[j] = 1;
13                 dlx.R[dlx.L[j]] = dlx.R[j];
14                 dlx.L[dlx.R[j]] = dlx.L[j];
15                 dlx.R[j] = dlx.L[j] = 0;
16             }
17     }
18     for (int i = 1; i <= row; i++)
19     {
20         for (int j = 1; j <= col; j++)
21         {
22             if (mtx[i][j] && !vis[j])
23                 dlx.Link(i, j);
24         }
25     }
26 }

 

代码:

  1 /********************************************
  2 *ACM Solutions
  3 *
  4 *@Title: POJ 1084 Square Destroyer
  5 *@Version: 1.0
  6 *@Time: 2014-09-29
  7 *@Solution: http://www.cnblogs.com/xysmlx/p/xxxxxxx.html
  8 *
  9 *@Author: xysmlx(Lingxiao Ma)
 10 *@Blog: http://www.cnblogs.com/xysmlx
 11 *@EMail: xysmlx@163.com
 12 *
 13 *Copyright (C) 2011-2015 xysmlx(Lingxiao Ma)
 14 ********************************************/
 15 // #pragma comment(linker, "/STACK:102400000,102400000")
 16 #include <cstdio>
 17 #include <iostream>
 18 #include <cstring>
 19 #include <string>
 20 #include <cmath>
 21 #include <set>
 22 #include <list>
 23 #include <map>
 24 #include <iterator>
 25 #include <cstdlib>
 26 #include <vector>
 27 #include <queue>
 28 #include <stack>
 29 #include <algorithm>
 30 #include <functional>
 31 using namespace std;
 32 typedef long long LL;
 33 #define pb push_back
 34 #define ROUND(x) round(x)
 35 #define FLOOR(x) floor(x)
 36 #define CEIL(x) ceil(x)
 37 const int maxn = 110;
 38 const int maxm = 0;
 39 const int inf = 0x3f3f3f3f;
 40 const LL inf64 = 0x3f3f3f3f3f3f3f3fLL;
 41 const double INF = 1e30;
 42 const double eps = 1e-6;
 43 const int P[4] = {0, 0, -1, 1};
 44 const int Q[4] = {1, -1, 0, 0};
 45 const int PP[8] = { -1, -1, -1, 0, 0, 1, 1, 1};
 46 const int QQ[8] = { -1, 0, 1, -1, 1, -1, 0, 1};
 47 
 48 /*
 49 重复覆盖:DLX
 50 输入:Link()
 51 输出:ans, bool Dance(int k)
 52 */
 53 const int maxnode = 360000;
 54 const int maxc = 500;
 55 const int maxr = 500;
 56 // const int inf = 0x3f3f3f3f;
 57 struct DLX
 58 {
 59     int L[maxnode], R[maxnode], D[maxnode], U[maxnode], C[maxnode];
 60     int S[maxc], H[maxr], size;
 61     int ans;
 62     ///不需要S域
 63     void Link(int r, int c)
 64     {
 65         S[c]++; C[size] = c;
 66         U[size] = U[c]; D[U[c]] = size;
 67         D[size] = c; U[c] = size;
 68         if (H[r] == -1) H[r] = L[size] = R[size] = size;
 69         else
 70         {
 71             L[size] = L[H[r]]; R[L[H[r]]] = size;
 72             R[size] = H[r]; L[H[r]] = size;
 73         }
 74         size++;
 75     }
 76     void remove(int c)
 77     {
 78         for (int i = D[c]; i != c; i = D[i])
 79             L[R[i]] = L[i], R[L[i]] = R[i];
 80     }
 81     void resume(int c)
 82     {
 83         for (int i = U[c]; i != c; i = U[i])
 84             L[R[i]] = R[L[i]] = i;
 85     }
 86     int h() ///用精确覆盖去估算剪枝
 87     {
 88         int ret = 0;
 89         bool vis[maxc];
 90         memset (vis, false, sizeof(vis));
 91         for (int i = R[0]; i; i = R[i])
 92         {
 93             if (vis[i])continue;
 94             ret++;
 95             vis[i] = true;
 96             for (int j = D[i]; j != i; j = D[j])
 97                 for (int k = R[j]; k != j; k = R[k])
 98                     vis[C[k]] = true;
 99         }
100         return ret;
101     }
102     //根据具体问题选择限制搜索深度或直接求解。
103     bool Dance(int k)
104     {
105         if (k + h() >= ans) return 0;
106         if (!R[0])
107         {
108             if (k < ans)ans = k;
109             return 1;
110         }
111         int c = R[0];
112         for (int i = R[0]; i; i = R[i])
113             if (S[i] < S[c])c = i;
114         for (int i = D[c]; i != c; i = D[i])
115         {
116             remove(i);
117             for (int j = R[i]; j != i; j = R[j])
118                 remove(j);
119             Dance(k + 1);
120             for (int j = L[i]; j != i; j = L[j])
121                 resume(j);
122             resume(i);
123         }
124         return 0;
125     }
126     void initL(int x) ///col is 1~x,row start from 1
127     {
128         for (int i = 0; i <= x; ++i)
129         {
130             S[i] = 0;
131             D[i] = U[i] = i;
132             L[i + 1] = i; R[i] = i + 1;
133         }///对列表头初始化
134         R[x] = 0;
135         size = x + 1; ///真正的元素从m+1开始
136         memset (H, -1, sizeof(H));
137         ///mark每个位置的名字
138     }
139 } dlx;
140 
141 int kase;
142 int n;
143 vector<int> vec;
144 bool mtx[maxn][maxn];
145 int row, col;
146 bool vis[maxn];
147 void init()
148 {
149     kase++;
150     vec.clear();
151     memset(mtx, 0, sizeof(mtx));
152     memset(vis, 0, sizeof(vis));
153 }
154 void input()
155 {
156     scanf("%d", &n);
157     int k;
158     scanf("%d", &k);
159     while (k--)
160     {
161         int x;
162         scanf("%d", &x);
163         vec.pb(x);
164     }
165 }
166 void debug()
167 {
168     //
169 }
170 void calmtx()
171 {
172     row = 2 * n * (n + 1);
173     col = 0;
174     for (int i = 1; i <= n; i++)
175         col += i * i;
176 
177     int cnt = 1;
178     for (int si = 1; si <= n; si++)
179     {
180         for (int i = 1; i <= n - si + 1; i++)
181         {
182             for (int j = 1; j <= n - si + 1; j++)
183             {
184                 for (int k = 0; k < si; k++)
185                 {
186                     mtx[(i - 1) * (2 * n + 1) + j + k][cnt] = 1;
187                     mtx[(i - 1 + si) * (2 * n + 1) + j + k][cnt] = 1;
188                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1)][cnt] = 1;
189                     mtx[i * n + (i - 1) * (n + 1) + j + k * (2 * n + 1) + si][cnt] = 1;
190                 }
191                 cnt++;
192             }
193         }
194     }
195 }
196 void build()
197 {
198     calmtx();
199 
200     dlx.initL(col);
201     for (int i = 0; i < vec.size(); i++)
202     {
203         int x = vec[i];
204         for (int j = 1; j <= col; j++)
205             if (mtx[x][j] && !vis[j])
206             {
207                 vis[j] = 1;
208                 dlx.R[dlx.L[j]] = dlx.R[j];
209                 dlx.L[dlx.R[j]] = dlx.L[j];
210                 dlx.R[j] = dlx.L[j] = 0;
211             }
212     }
213     // for (int i = 1; i <= col; i++)
214     //     cout << vis[i] << " ";
215     // cout << endl;
216     for (int i = 1; i <= row; i++)
217     {
218         for (int j = 1; j <= col; j++)
219         {
220             if (mtx[i][j] && !vis[j])
221                 dlx.Link(i, j);
222         }
223     }
224 }
225 void solve()
226 {
227     build();
228     // for (int i = 1; i <= row; i++)
229     // {
230     //     for (int j = 1; j <= col; j++)
231     //     {
232     //         cout << mtx[i][j] << " ";
233     //     }
234     //     cout << endl;
235     // }
236     // cout << row << " " << col << endl;
237     dlx.ans = inf;
238     dlx.Dance(0);
239     printf("%d\n", dlx.ans);
240 }
241 void output()
242 {
243     //
244 }
245 int main()
246 {
247     // int size = 256 << 20; // 256MB
248     // char *p = (char *)malloc(size) + size;
249     // __asm__("movl %0, %%esp\n" :: "r"(p));
250 
251     // std::ios_base::sync_with_stdio(false);
252 #ifdef xysmlx
253     freopen("in.cpp", "r", stdin);
254 #endif
255 
256     kase = 0;
257     int T;
258     scanf("%d", &T);
259     while (T--)
260     {
261         init();
262         input();
263         solve();
264         output();
265     }
266     return 0;
267 }
POJ 1084

 

posted @ 2014-09-29 16:49  xysmlx  阅读(399)  评论(0编辑  收藏  举报