【UVa10606】Mines For Diamonds 题解(bfs+枚举)

新博客:debug18.com 使用hexo搭建,欢迎来踩~

传送门:https://uva.onlinejudge.org/external/106/10605.pdf


题目大意:给你一个N * M的矩阵,一些格子中分布着钻石(地雷),需要找到若干条不分岔的从边界开始延伸的道路,可以覆盖所有的钻石。求这些道路覆盖的最小方格数。下图中的答案为11。


 

看到题首先想到用bfs预处理出每对钻石之间的距离以及每个钻石到边界的最短距离,这个可以由对每个钻石bfs求出。

接下来枚举钻石的排列,枚举出来排列之后就可以贪心扫一遍了。具体来说,依次考虑每个钻石,对于一个钻石既可以选择连向后一个,也可以选择不连成为这条链的终点,然后下一个钻石再向墙连边。这两种决策贪心取最小即可。时间复杂度O(N!*N),可以接受。

(其实这个算法有个漏洞:无法防止路径交叉的情况出现。然而我并不能证明路径交叉的情况一定不是最小值,只能脑补一下了……)

这样的话貌似建个图跑个最短路也能过……吗?


请勿吐槽变量名……

代码(299msAC):

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <cctype>
  6 #include <cassert>
  7 #include <ctime>
  8 #include <algorithm>
  9 #include <utility>
 10 #include <functional>
 11 
 12 #define X first
 13 #define Y second
 14 #define MP make_pair
 15 #define BP push_back
 16 #define SZ(x) ((int)(x).size())
 17 #define ALL(x) (x).begin(), (x).end()
 18 #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
 19 
 20 using namespace std;
 21 
 22 typedef long long LL;
 23 typedef pair<int, int> Pii;
 24 
 25 const int oo = 0x3f3f3f3f;
 26 
 27 template<class T> T read(T &x)
 28 {
 29     T f = 1;
 30     char ch = getchar();
 31     while (!isdigit(ch)) {
 32         if (ch == '-')
 33             f = -1;
 34         ch = getchar();
 35     }
 36     for (x = 0; isdigit(ch); ch = getchar())
 37         x = 10 * x + ch - '0';
 38 
 39     return x *= f;
 40 }
 41 
 42 const int MAXN = 15, FUCKER_SIZE = 15;
 43 const int dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0, 1};
 44 
 45 int N, M;
 46 int A[MAXN][MAXN];
 47 int totFucker;
 48 Pii fucker[FUCKER_SIZE];
 49 
 50 int dist[FUCKER_SIZE][FUCKER_SIZE];
 51 
 52 void bfs(int s)
 53 {
 54     static int dis[MAXN][MAXN];
 55     static Pii q[MAXN*MAXN];
 56     int front = 0, rear = 0;
 57     memset(dis, 0, sizeof(dis));
 58     q[rear++] = fucker[s];
 59     dis[fucker[s].X][fucker[s].Y] = 1;
 60     while (front != rear) {
 61         Pii u = q[front++];
 62         for (int i = 0; i < 4; i++) {
 63             Pii v(u.X + dx[i], u.Y + dy[i]);
 64             if (v.X == 0 || v.Y == 0 || v.X > N || v.Y > M || dis[v.X][v.Y])
 65                 continue;
 66 
 67             dis[v.X][v.Y] = dis[u.X][u.Y] + 1;
 68             if (A[v.X][v.Y] == 0) {
 69                 if (dist[s][0] == 0)
 70                     dist[s][0] = dis[v.X][v.Y] - 1;
 71             } else {
 72                     q[rear++] = v;
 73                     if (A[v.X][v.Y] > 1)
 74                         dist[s][A[v.X][v.Y]-1] = dis[v.X][v.Y] - 1;
 75             }
 76         }
 77     }
 78 }
 79 
 80 int main()
 81 {
 82 #ifndef ONLINE_JUDGE
 83     freopen("tmp.in" ,"r", stdin);
 84     freopen("tmp.out", "w", stdout);
 85 #endif // ONLINE_JUDGE
 86     int T;
 87     read(T);
 88     while (T--) {
 89         read(N); read(M);
 90         totFucker = 0;
 91         for (int i = 1; i <= N; i++) {
 92             static char inp[MAXN];
 93             scanf("%s", inp);
 94             for (int j = 1; j <= M; j++) {
 95                 if (inp[j-1] == '#')
 96                     A[i][j] = 0;
 97                 else if (inp[j-1] == '.')
 98                     A[i][j] = 1;
 99                 else {
100                     A[i][j] = 1 + (++totFucker);
101                     fucker[totFucker] = MP(i, j);
102                 }
103             }
104         }
105 
106         for (int i = 1; i <= totFucker; i++) {
107             memset(dist[i], 0, sizeof(dist[i]));
108             bfs(i);
109         }
110 
111         static int p[FUCKER_SIZE];
112         int ans = 0;
113         for (int i = 1; i <= totFucker; i++) {
114             ans += dist[i][0];
115             p[i] = i;
116         }
117         do {
118             int res = dist[p[1]][0];
119             for (int i = 1; i < totFucker; i++) {
120                 res += min(dist[p[i]][p[i+1]], dist[p[i+1]][0]);
121                 if (res + totFucker - i - 1 > ans) {
122                     res = oo;
123                     break;
124                 }
125             }
126             ans = min(ans, res);
127         } while (next_permutation(p + 1, p + 1 + totFucker));
128 
129         printf("%d\n", ans);
130 
131     }
132 
133     return 0;
134 }

posted on 2015-08-09 21:23  __debug  阅读(526)  评论(0编辑  收藏  举报

导航