【POJ】1084 Square Destroyer

1. 题目描述
由$n \times n, n \in [1, 5]$的正方形由$2 \times n \times (n+1)$根木棍组成,可能已经有些木棍被破坏,求至少还需破坏多少木根,可以使得不存在任何正方形?

2. 基本思路
这是一道非常有趣的题目,可以使用IDA*解也可以用DLX解。可以试试5 0这组数据比较两者的性能差异。
(1) IDA*
使用IDA*处理,是因为最后的解的范围一定不是很大,因为数据很小。至多也就60根木棍。
首先可以预处理分别对正方形和木棍进行编号,进而预处理破坏每根木棍可以影响的正方形。
由于木棍和正方形都不超过60个,因此可以采用longlong进行状态压缩,一定要装压,否则就哭吧。
每次选择当前仍然存在的最小正方形,然后枚举它的每条边进行深搜。

(2) DLX
使用DLX解这道题很容易理解, 而且解5 0这组数据也很快。
首先仍然可以使用上述的预处理方法。从而可以得到当前木棍中仍然存在的正方形。
如果,当前不存在正方形则直接输出0。否则以正方形的个数初始化DLX。
接下来,枚举每条边,搜索它可以影响到的正方形,建立一个可行方案。
直接套用DLX可解,注意DLX加入H函数可以加速,而且效果还是挺明显的。

3. 代码
(1)IDA*

  1 /* 1084 */
  2 #include <iostream>
  3 #include <sstream>
  4 #include <string>
  5 #include <map>
  6 #include <queue>
  7 #include <set>
  8 #include <stack>
  9 #include <vector>
 10 #include <deque>
 11 #include <bitset>
 12 #include <algorithm>
 13 #include <cstdio>
 14 #include <cmath>
 15 #include <ctime>
 16 #include <cstring>
 17 #include <climits>
 18 #include <cctype>
 19 #include <cassert>
 20 #include <functional>
 21 #include <iterator>
 22 #include <iomanip>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,1024000")
 25 
 26 #define sti                set<int>
 27 #define stpii            set<pair<int, int> >
 28 #define mpii            map<int,int>
 29 #define vi                vector<int>
 30 #define pii                pair<int,int>
 31 #define vpii            vector<pair<int,int> >
 32 #define rep(i, a, n)     for (int i=a;i<n;++i)
 33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 34 #define clr                clear
 35 #define pb                 push_back
 36 #define mp                 make_pair
 37 #define fir                first
 38 #define sec                second
 39 #define all(x)             (x).begin(),(x).end()
 40 #define SZ(x)             ((int)(x).size())
 41 #define lson            l, mid, rt<<1
 42 #define rson            mid+1, r, rt<<1|1
 43 #define INF                0x3f3f3f3f
 44 #define mset(a, val)    memset(a, (val), sizeof(a))
 45 
 46 #define LL long long
 47 
 48 typedef struct {
 49     vector<LL> sq;
 50     int sz;
 51 } sqInfo_t;
 52 
 53 
 54 const int maxm = 65;
 55 int rowId[6][6];
 56 int colId[6][6];
 57 int n, tot;
 58 LL st;
 59 sqInfo_t sqInfo[6];
 60 
 61 void init_sq(int n) {
 62     int cnt = 0;
 63     sqInfo_t& info = sqInfo[n];
 64     vector<LL>& sq = info.sq;
 65     int& sz = info.sz;
 66     
 67     rep(i, 0, n) {
 68         rep(j, 0, n)
 69             rowId[i][j] = cnt++;
 70         rep(j, 0, n+1)
 71             colId[i][j] = cnt++;
 72     }
 73     rep(j, 0, n)
 74         rowId[n][j] = cnt++;
 75 
 76     cnt = 0;
 77     rep(i, 0, n) {
 78         rep(j, 0, n) {
 79             rep(k, 1, n+1) {
 80                 if (i+k>n || j+k>n)
 81                     break;
 82 
 83                 LL val = 0;
 84 
 85                 // Top
 86                 rep(l, 0, k) {
 87                     val |= (1LL << rowId[i][j+l]);
 88                 }
 89 
 90                 // Left
 91                 rep(l, 0, k) {
 92                     val |= (1LL << colId[i+l][j]);
 93                 }
 94 
 95                 // Down
 96                 rep(l, 0, k) {
 97                     val |= (1LL << rowId[i+k][j+l]);
 98                 }
 99 
100                 // Right
101                 rep(l, 0, k) {
102                     val |= (1LL << colId[i+l][j+k]);
103                 }
104                 
105                 sq.pb(val);
106                 ++sz;
107             }
108         }
109     }
110 }
111 
112 void init() {
113     rep(i, 1, 6)
114         init_sq(i);
115 }
116 
117 
118 bool dfs(int m, LL cst) {
119     const int& sz = sqInfo[n].sz;
120     const vector<LL>& sq = sqInfo[n].sq;
121     int h = 0;
122     LL st = -1, tmp = cst;
123     
124     rep(i, 0, sz) {
125         if ((tmp & sq[i]) == sq[i]) {
126             ++h;
127             tmp ^= sq[i];
128             if (st < 0)
129                 st = sq[i];
130         }
131     }
132     
133     if(h == 0)
134         return true;
135     
136     if (m < h)
137         return false;
138     
139     rep(i, 0, tot) {
140         if (st & (1LL << i)) {
141             if ( dfs(m-1, cst^(1LL<<i)) )    return true;
142         }
143     }
144     return false;
145 }
146 
147 void solve() {
148     int ans = -1;
149 
150     for (int i=0; i<=tot; ++i) {
151         if (dfs(i, st)) {
152             ans = i;
153             break;
154         }
155     }
156 
157     printf("%d\n", ans);
158 }
159 
160 int main() {
161     ios::sync_with_stdio(false);
162     #ifndef ONLINE_JUDGE
163         freopen("data.in", "r", stdin);
164         freopen("data.out", "w", stdout);
165     #endif
166 
167     int t;
168 
169     init();
170     scanf("%d", &t);
171     while (t--) {
172         scanf("%d", &n);
173         tot = n*(n+1)*2;
174         int k, x;
175         st = (1LL << tot) - 1;
176 
177         scanf("%d", &k);
178         while (k--) {
179             scanf("%d", &x);
180             --x;
181             st ^= (1LL << x);
182         }
183         solve();
184     }
185 
186     #ifndef ONLINE_JUDGE
187         printf("time = %d.\n", (int)clock());
188     #endif
189 
190     return 0;
191 }

(2)Dancing Links

  1 /* 1084 */
  2 #include <iostream>
  3 #include <sstream>
  4 #include <string>
  5 #include <map>
  6 #include <queue>
  7 #include <set>
  8 #include <stack>
  9 #include <vector>
 10 #include <deque>
 11 #include <bitset>
 12 #include <algorithm>
 13 #include <cstdio>
 14 #include <cmath>
 15 #include <ctime>
 16 #include <cstring>
 17 #include <climits>
 18 #include <cctype>
 19 #include <cassert>
 20 #include <functional>
 21 #include <iterator>
 22 #include <iomanip>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,1024000")
 25 
 26 #define sti                set<int>
 27 #define stpii            set<pair<int, int> >
 28 #define mpii            map<int,int>
 29 #define vi                vector<int>
 30 #define pii                pair<int,int>
 31 #define vpii            vector<pair<int,int> >
 32 #define rep(i, a, n)     for (int i=a;i<n;++i)
 33 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 34 #define clr                clear
 35 #define pb                 push_back
 36 #define mp                 make_pair
 37 #define fir                first
 38 #define sec                second
 39 #define all(x)             (x).begin(),(x).end()
 40 #define SZ(x)             ((int)(x).size())
 41 #define lson            l, mid, rt<<1
 42 #define rson            mid+1, r, rt<<1|1
 43 #define INF                0x3f3f3f3f
 44 #define mset(a, val)    memset(a, (val), sizeof(a))
 45 
 46 #define LL __int64
 47 
 48 typedef struct {
 49     static const int maxr = 65;
 50     static const int maxc = 65;
 51     static const int maxn = maxr * maxc;
 52 
 53     int n, sz;
 54     int S[maxc];
 55     bool visit[maxc];
 56 
 57     int col[maxn];
 58     int L[maxn], R[maxn], U[maxn], D[maxn];
 59 
 60     int ansd;
 61 
 62     void init(int _n) {
 63         n = _n;
 64 
 65         rep(i, 0, n+1) {
 66             L[i] = i - 1;
 67             R[i] = i + 1;
 68             U[i] = i;
 69             D[i] = i;
 70             col[i] = i;
 71         }
 72 
 73         L[0] = n;
 74         R[n] = 0;
 75 
 76         sz = n + 1;
 77         memset(S, 0, sizeof(S));
 78         ansd = INF;
 79     }
 80 
 81     void addRow(const vi& columns) {
 82         int first = sz;
 83         int size = SZ(columns);
 84 
 85         rep(i, 0, size) {
 86             const int& c = columns[i];
 87 
 88             L[sz] = sz - 1;
 89             R[sz] = sz + 1;
 90 
 91             D[sz] = c;
 92             U[sz] = U[c];
 93             D[U[c]] = sz;
 94             U[c] = sz;
 95 
 96             col[sz] = c;
 97 
 98             ++S[c];
 99             ++sz;
100         }
101 
102         L[first] = sz - 1;
103         R[sz-1] = first;
104     }
105 
106     void remove_col(int c) {
107         for (int i=D[c]; i!=c; i=D[i]) {
108             L[R[i]] = L[i];
109             R[L[i]] = R[i];
110             --S[col[i]];
111         }
112     }
113 
114     void restore_col(int c) {
115         for (int i=D[c]; i!=c; i=D[i]) {
116             L[R[i]] = i;
117             R[L[i]] = i;
118             ++S[col[i]];
119         }
120     }
121 
122     int H() {
123         int ret = 0;
124 
125         memset(visit, false, sizeof(visit));
126         for (int i=R[0]; i; i=R[i]) {
127             if (visit[col[i]])
128                 continue;
129 
130             ++ret;
131             visit[col[i]] = true;
132             for (int j=D[i]; j!=i; j=D[j]) {
133                 for (int k=R[j]; k!=j; k=R[k]) {
134                     visit[col[k]] = true;
135                 }
136             }
137         }
138 
139         return ret;
140     }
141 
142     void dfs(int d) {
143         int delta = H();
144 
145         if (d+delta >= ansd)
146             return ;
147 
148         if (R[0] == 0) {
149             ansd = d;
150             return ;
151         }
152 
153         int c = R[0];
154         for (int i=R[0]; i; i=R[i]) {
155             if (S[i] < S[c])
156                 c = i;
157         }
158 
159         for (int i=D[c]; i!=c; i=D[i]) {
160             remove_col(i);
161             for (int j=R[i]; j!=i; j=R[j]) {
162                 remove_col(j);
163             }
164             dfs(d + 1);
165             for (int j=L[i]; j!=i; j=L[j]) {
166                 restore_col(j);
167             }
168             restore_col(i);
169         }
170     }
171 
172 } DLX;
173 
174 typedef struct {
175     vector<LL> sq;
176     int sz;
177 } sqInfo_t;
178 
179 DLX solver;
180 const int maxm = 65;
181 bool mark[maxm];
182 int valid[maxm];
183 int rowId[6][6];
184 int colId[6][6];
185 int n, tot;
186 LL st;
187 sqInfo_t sqInfo[6];
188 
189 void init_sq(int n) {
190     int cnt = 0;
191     sqInfo_t& info = sqInfo[n];
192     vector<LL>& sq = info.sq;
193     int& sz = info.sz;
194 
195     rep(i, 0, n) {
196         rep(j, 0, n)
197             rowId[i][j] = cnt++;
198         rep(j, 0, n+1)
199             colId[i][j] = cnt++;
200     }
201     rep(j, 0, n)
202         rowId[n][j] = cnt++;
203 
204     cnt = 0;
205     rep(i, 0, n) {
206         rep(j, 0, n) {
207             rep(k, 1, n+1) {
208                 if (i+k>n || j+k>n)
209                     break;
210 
211                 LL val = 0;
212 
213                 // Top
214                 rep(l, 0, k) {
215                     val |= (1LL << rowId[i][j+l]);
216                 }
217 
218                 // Left
219                 rep(l, 0, k) {
220                     val |= (1LL << colId[i+l][j]);
221                 }
222 
223                 // Down
224                 rep(l, 0, k) {
225                     val |= (1LL << rowId[i+k][j+l]);
226                 }
227 
228                 // Right
229                 rep(l, 0, k) {
230                     val |= (1LL << colId[i+l][j+k]);
231                 }
232 
233                 sq.pb(val);
234                 ++sz;
235             }
236         }
237     }
238 }
239 
240 void init() {
241     rep(i, 1, 6)
242         init_sq(i);
243 }
244 
245 void solve() {
246     const vector<LL>& sq = sqInfo[n].sq;
247     const int& sz = sqInfo[n].sz;
248     int m = 0;
249 
250     rep(i, 0, sz) {
251         if ((st & sq[i]) == sq[i]) {
252             valid[m++] = i;
253         }
254     }
255 
256     if (m == 0) {
257         puts("0");
258         return ;
259     }
260 
261     solver.init(m);
262 
263     rep(i, 0, tot) {
264         if (mark[i]) {
265             vi vc;
266 
267             rep(j, 0, m) {
268                 if (sq[valid[j]] & (1LL << i))
269                     vc.pb(j+1);
270             }
271 
272             if (SZ(vc) > 0) {
273                 solver.addRow(vc);
274             }
275         }
276     }
277 
278     solver.dfs(0);
279     int ans = solver.ansd;
280 
281     printf("%d\n", ans);
282 }
283 
284 int main() {
285     ios::sync_with_stdio(false);
286     #ifndef ONLINE_JUDGE
287         freopen("data.in", "r", stdin);
288         freopen("data.out", "w", stdout);
289     #endif
290 
291     int t;
292 
293     init();
294     scanf("%d", &t);
295     while (t--) {
296         scanf("%d", &n);
297         memset(mark, true, sizeof(mark));
298         tot = n*(n+1)*2;
299         int k, x;
300         st = (1LL << tot) - 1;
301 
302         scanf("%d", &k);
303         while (k--) {
304             scanf("%d", &x);
305             mark[--x] = false;
306             st ^= (1LL << x);
307         }
308         solve();
309     }
310 
311     #ifndef ONLINE_JUDGE
312         printf("time = %d.\n", (int)clock());
313     #endif
314 
315     return 0;
316 }

4. 数据生成器

 1 import sys
 2 import string
 3 from random import randint, shuffle
 4 
 5     
 6 def GenData(fileName):
 7     with open(fileName, "w") as fout:
 8         t = 20
 9         fout.write("%d\n" % (t))
10         for tt in xrange(t):
11             n = randint(1, 5)
12             tot = n * (n + 1)
13             taken = randint(1, tot)
14             L = range(1, tot+1)
15             shuffle(L)
16             fout.write("%d %d\n" % (n, taken))
17             fout.write(" ".join(map(str, L[:taken])) + "\n")
18             
19             
20 def MovData(srcFileName, desFileName):
21     with open(srcFileName, "r") as fin:
22         lines = fin.readlines()
23     with open(desFileName, "w") as fout:
24         fout.write("".join(lines))
25 
26         
27 def CompData():
28     print "comp"
29     srcFileName = "F:\Qt_prj\hdoj\data.out"
30     desFileName = "F:\workspace\cpp_hdoj\data.out"
31     srcLines = []
32     desLines = []
33     with open(srcFileName, "r") as fin:
34         srcLines = fin.readlines()
35     with open(desFileName, "r") as fin:
36         desLines = fin.readlines()
37     n = min(len(srcLines), len(desLines))-1
38     for i in xrange(n):
39         ans2 = int(desLines[i])
40         ans1 = int(srcLines[i])
41         if ans1 > ans2:
42             print "%d: wrong" % i
43 
44             
45 if __name__ == "__main__":
46     srcFileName = "F:\Qt_prj\hdoj\data.in"
47     desFileName = "F:\workspace\cpp_hdoj\data.in"
48     GenData(srcFileName)
49     MovData(srcFileName, desFileName)
View Code

 

转载于:https://www.cnblogs.com/bombe1013/p/5322605.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值