zoukankan      html  css  js  c++  java
  • 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); else
    101     if (c <= a && c <= b) swap(a, c);
    102     ans = a;
    103     dfs(1, 0);
    104     printf("%d
    ", ans);
    105   }
    106   return 0;
    107 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    反向迭代
    c++知识点
    LeetCode-Count Bits
    LeetCode-Perfect Rectangle
    LeetCode-Perfect Squares
    LeetCode-Lexicographical Numbers
    LeetCode-Find Median from Data Stream
    LeetCode-Maximal Square
    LeetCode-Number of Digit One
    LeetCode-Combination Sum IV
  • 原文地址:https://www.cnblogs.com/rausen/p/4256568.html
Copyright © 2011-2022 走看看