hdu 3468 Treasure Hunting

二分图匹配

题意: 。。。 看了半天

我们可以从rally点出发到最近的rally点, 如果有treasure在这两个rally点的最短路径上, 我们可以拿走他。

思路也可以参见http://blog.csdn.net/wall_f/article/details/8990937

这种分析问题的思路太值得学习了。。

一开始没看懂题。。 在vj上找了个代码 (o(╯□╰)o。。 谴责一下自己。。)然后写了一下注释。。

写完注释发现就那么回事 不想再敲一遍了。。噗。。

  1 /*Author :usedrose  */
  2 /*Created Time :2015/8/3 21:00:00*/
  3 /*File Name :2.cpp*/
  4 #pragma comment(linker, "/STACK:1024000000,1024000000") 
  5 #include <cstdio>
  6 #include <iostream>
  7 #include <algorithm>
  8 #include <sstream>
  9 #include <cstdlib>
 10 #include <cstring>
 11 #include <climits>
 12 #include <vector>
 13 #include <string>
 14 #include <ctime>
 15 #include <cmath>
 16 #include <deque>
 17 #include <queue>
 18 #include <stack>
 19 #include <set>
 20 #include <map>
 21 #define INF 0x3f3f3f3f
 22 #define eps 1e-8
 23 #define pi acos(-1.0)
 24 #define MAXN 1110
 25 #define MAXM 100110
 26 #define OK cout << "ok" << endl;
 27 #define o(a) cout << #a << " = " << a << endl
 28 #define o1(a,b) cout << #a << " = " << a << "  " << #b << " = " << b << endl
 29 using namespace std;
 30 typedef long long LL;
 31 
 32 int vv[MAXM], nxt[MAXM], h[MAXN*MAXN], e;
 33 char str[MAXN][MAXN];
 34 int n, m;
 35 int dis[55][MAXN*MAXN];
 36 int d[MAXN][MAXN];
 37 int bx[MAXN], by[MAXN];
 38 
 39 void addedge(int u,int v)
 40 {
 41     vv[e] = v;
 42     nxt[e] = h[u];
 43     h[u] = e++;
 44 }
 45 
 46 int vis[MAXN*MAXN], pre[MAXN*MAXN];
 47 int dx[] = {0, 0, 1, -1};
 48 int dy[] = {1, -1, 0, 0};
 49 
 50 int getid(char x)
 51 {
 52     if (isupper(x)) return x - 'A';
 53     if (islower(x)) return x - 'a' + 26;
 54     if (x == '*') return -1;
 55     return -2;
 56 }
 57 
 58 int getid(int x, int y)
 59 {
 60     return x*m + y;
 61 }
 62 
 63 bool inside(int x, int y)
 64 {
 65     return x >= 0 && x < n && y >= 0 && y < m;
 66 }
 67 
 68 
 69 void bfs(int x, int y)
 70 {
 71     queue<int> q;
 72     memset(d, -1, sizeof(d));
 73     q.push(x), q.push(y);
 74     d[x][y] = 0;
 75     while (!q.empty()) {
 76         x = q.front(); q.pop();
 77         y = q.front(); q.pop();
 78         for (int i = 0;i < 4; ++ i) {
 79             int x1 = x + dx[i];
 80             int y1 = y + dy[i];
 81             if (inside(x1, y1) && str[x1][y1] != '#' && d[x1][y1] < 0) {
 82                 d[x1][y1] = d[x][y] + 1;
 83                 q.push(x1); q.push(y1);
 84             }
 85         }
 86     }
 87 }
 88 
 89 bool init()
 90 {
 91     memset(bx, -1, sizeof(bx));
 92     for (int i = 0;i < n; ++ i)
 93         for (int j = 0;j < m;++ j) {
 94             int x = getid(str[i][j]); 
 95             if (x >= 0) {                // if it is a rally point
 96                 bx[x] = i, by[x] = j;     //note its position
 97                 bfs(i, j);                // get the shortest path around it
 98                 for (int k = 0;k < n; ++ k)
 99                     for (int l = 0;l < m; ++ l) {
100                         dis[x][k*m+l] = d[k][l];    // get the distances from the point to all nodes
101                         if (getid(str[k][l]) >= 0 && d[k][l] == -1) return false;// if unreachable 
102                     }
103             }
104         }
105     for (int i = 0;i < n; ++ i)
106         for (int j = 0;j < m; ++ j) if (str[i][j] == '*') { // for all treasure
107             for (int k = 1;bx[k] != -1; ++ k) {// for all rally points
108                 if (dis[k-1][i*m+j] + dis[k][i*m+j] == dis[k-1][getid(bx[k],by[k])]) // if treasure on the shortest path between two rallys
109                     if (dis[k-1][i*m+j] != -1 && dis[k][i*m+j] != -1)
110                         addedge(k, i*m+j);            //we should add an edge
111             }
112         }
113     return true;
114 }
115 
116 int dfs(int u)
117 {
118     for (int i = h[u]; i + 1;i = nxt[i]) {
119         int v = vv[i];
120         if (vis[v]) continue;
121         vis[v] = 1;
122         if (pre[v] == -1 || dfs(pre[v])) {
123             pre[v] = u;
124             return 1;
125         }
126     }
127     return 0;
128 }
129 
130 int solve()
131 {
132     if (!init()) return -1;
133     int ans = 0;
134     memset(pre, -1, sizeof(pre));
135     for (int i = 1; bx[i] != -1;++ i) {
136         memset(vis, 0 ,sizeof(vis));
137         ans += dfs(i);
138     }
139     return ans;
140 }
141 
142 int main()
143 {
144     while (cin >> n >> m) {
145         memset(h, -1, sizeof(h));
146         e = 0;
147         for (int i = 0;i < n; ++ i) 
148             cin >> str[i];
149         cout << solve() << endl;
150     }
151     return 0;
152 }

 

posted @ 2015-08-03 22:19  UsedRose  阅读(228)  评论(0编辑  收藏  举报