1. 程式人生 > >HDU 1045 Fire Net(搜尋剪枝)

HDU 1045 Fire Net(搜尋剪枝)

http://acm.split.hdu.edu.cn/showproblem.php?pid=1045

題目連結(總有一個可以點開)……

題意:給出一張地圖,上面只有兩種字元(.和X),X相當於無法穿透的牆。問這張地圖上最多可以放置多少個互不攻擊的子彈……

第一反應是搜尋,然而後來看到網上有些大神說這是二分圖匹配……看來還是要研究下。

我剪枝的思路:對每個點設定所有關聯的點(上下左右四個方向直到被牆擋住),每個點依次存放關聯點。這樣每次搜尋的時候就可以省一些時間,同時降低程式設計複雜度。

每次搜到的子彈數都用ans[]存下(ans[i]true意為可能存在大於i的可行方案),操作的時候二維表變成一位表(這樣方便)。

例如有張4*4的表:

(0,0)->(0)

(0,1)->(1)

...

(1,0)->(4)

...

(3,3)->(15)

具體就是這樣。

程式碼如下:

 1 #include <cstdio>
 2 #include <vector>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 #include <functional>
 7 
 8 using namespace std;
 9 
10 #define
REP(i,n) for(int i(0); i < (n); ++i) 11 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 12 #define dec(i,a,b) for(int i(a); i >= (b); --i) 13 #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) 14 15 #define LL long long 16 #define ULL unsigned long long 17
#define MP make_pair 18 #define PB push_back 19 #define FI first 20 #define SE second 21 #define INF 1 << 30 22 23 const int N = 100000 + 10; 24 const int M = 10000 + 10; 25 const int Q = 100 + 10; 26 const int A = 6 + 1; 27 28 vector <int> v[Q]; 29 int c[A][A], h[A][A]; 30 char st[Q]; 31 bool f[Q], ans[Q]; 32 int n, num, ret; 33 34 void dfs(int k, int low, bool * f){ 35 ans[k] = true; bool now = true; REP(i, n * n) if (!f[i]) { now = false; break; } if (now) return; int d[Q]; 36 REP(j, num) d[j] = f[j]; rep(i, low, num - 1) if (!f[i]){ f[i] = true; REP(j, v[i].size()) f[v[i][j]] = true; dfs(k + 1, low + 1, f); REP(j, num) f[j] = d[j];} 37 } 38 39 40 int main(){ 41 #ifndef ONLINE_JUDGE 42 freopen("test.txt", "r", stdin); 43 freopen("test.out", "w", stdout); 44 #endif 45 46 while (~scanf("%d", &n), n){ 47 REP(i, n){ scanf("%s", st); REP(j, n) c[i][j] = st[j] == '.' ? 0 : 1; } 48 //REP(i, n){ REP(j, n) putchar(c[i][j] + 48); putchar(10);} 49 int cnt = 0; REP(i, n) REP(j, n) h[i][j] = cnt++; 50 REP(i, n * n + 10) v[i].clear(); num = n * n; 51 REP(i, n) REP(j, n) if (!c[i][j]){ 52 rep(k, j + 1, n - 1){ if (c[i][k]) break; v[h[i][j]].PB(h[i][k]); } 53 rep(k, i + 1, n - 1){ if (c[k][j]) break; v[h[i][j]].PB(h[k][j]); } 54 dec(k, j - 1, 0){ if (c[i][k]) break; v[h[i][j]].PB(h[i][k]); } 55 dec(k, i - 1, 0){ if (c[k][j]) break; v[h[i][j]].PB(h[k][j]); } 56 } 57 //REP(i, n) REP(j, n){ printf("%d %d: ", i, j); REP(k, v[h[i][j]].size()) printf("%d ", v[h[i][j]][k]); puts("");} puts(""); 58 memset(ans, false, sizeof ans); REP(i, n) REP(j, n) f[h[i][j]] = c[i][j]; 59 REP(i, n) REP(j, n) if (!c[i][j]) dfs(0, h[i][j], f); 60 ret = 0; dec(i, num, 0) if (ans[i]){ ret = i; break;} 61 printf("%d\n", ret); 62 } 63 64 65 return 0; 66 67 }
View Code

HDU上 0MS..手動勝利!!(資料好像蠻弱的)