首页 > 代码库 > BZOJ3140 [Hnoi2013]消毒

BZOJ3140 [Hnoi2013]消毒

首先分析题目:

"对(x, y, z)的立方体消毒,cost = min(x, y, z)"

所以由贪心的想法,我们可以对(1, y, z)的立方体消毒,cost = 1,这一定是最优的cost为1的解法

又a * b * c ≤ 5000, 不妨设a = min(a, b, c) ≤ 17,故我们可以枚举a方向哪些(1, b, c)的立方体被消毒了。

然后把剩下的部分压成一个(b, c)的矩形,于是就变成经典问题最小点覆盖了,转化成二分图最大匹配来做。

 

技术分享
  1 /**************************************************************  2     Problem: 3140  3     User: rausen  4     Language: C++  5     Result: Accepted  6     Time:1324 ms  7     Memory:1312 kb  8 ****************************************************************/  9   10 #include <cstdio> 11 #include <algorithm> 12 #include <cstring> 13   14 using namespace std; 15 const int N = 5005; 16   17 int a, b, c, ans; 18 int first[N], tot, cnt_p, now_time; 19 int l[N], vis[N]; 20 bool u[20]; 21   22 struct point { 23   int x, y, z; 24   point() {} 25   point(int _x, int _y, int _z) : x(_x), y(_y), z(_z) { 26     if (b <= a && b <= c) swap(x, y); else 27     if (c <= a && c <= b) swap(x, z); 28   } 29 } p[N]; 30   31 struct edge { 32   int next, to; 33   edge() {} 34   edge(int _n, int _t) : next(_n), to(_t) {} 35 } e[N * 10]; 36   37 int read() { 38   int x = 0; 39   char ch = getchar(); 40   while (ch < 0 || 9 < ch) 41     ch = getchar(); 42   while (0 <= ch && ch <= 9) 43     (x *= 10) += ch - 0, ch = getchar(); 44   return x; 45 } 46   47 inline void add_edge(int x, int y) { 48   e[++tot] = edge(first[x], y), first[x] = tot; 49 } 50   51 #define y e[x].to 52 bool find(int p) { 53   int x; 54   for (x = first[p]; x; x = e[x].next) 55     if (vis[y] != now_time) { 56       vis[y] = now_time; 57       if (!l[y] || find(l[y])) { 58     l[y] = p; 59     return 1; 60       } 61     } 62   return 0; 63 } 64 #undef y 65   66 inline void work(int res) { 67   int i; 68   tot = 0; 69   for (i = 1; i <= b; ++i) first[i] = 0; 70   for (i = 1; i <= c; ++i) l[i + b] = 0; 71   for (i = 1; i <= cnt_p; ++i) 72     if (!u[p[i].x]) 73       add_edge(p[i].y, p[i].z + b); 74   for (i = 1; i <= b; ++i) { 75     ++now_time; 76     if ((res += find(i)) > ans) return; 77   } 78   ans = res; 79 } 80   81 void dfs(int step, int now_ans) { 82   if (now_ans > ans) return; 83   if (step > a) { 84     work(now_ans); 85     return; 86   } 87   u[step] = 1, dfs(step + 1, now_ans + 1); 88   u[step] = 0, dfs(step + 1, now_ans); 89 } 90   91 int main() { 92   int i, j, k, T; 93   T = read(); 94   while (T--) { 95     a = read(), b = read(), c = read(), cnt_p = 0; 96     for (i = 1; i <= a; ++i) 97       for (j = 1; j <= b; ++j) 98     for (k = 1; k <= c; ++k) 99       if (read()) p[++cnt_p] = point(i, j, k);100     if (b <= a && b <= c) swap(a, b); else101     if (c <= a && c <= b) swap(a, c);102     ans = a;103     dfs(1, 0);104     printf("%d\n", ans);105   }106   return 0;107 }
View Code

 

BZOJ3140 [Hnoi2013]消毒