zoukankan      html  css  js  c++  java
  • BZOJ3144 [Hnoi2013]切糕

    Orz 黄学长好腻害!

    首先题目就是要求在一个P*Q的格子里填数,不同的数代价不同,要求相邻的格子差小于D,求最小代价。

    最小割模型,我们把一个格子拆成R个点

    (x, y, z)向(x, y, z + 1)连边,边权f(x, y, z + 1)

    (x, y, z)向(x + dx, y + dy, z - d)连边,边权inf

    然后割一下就好了,正确性嘛。。。应该是对的。。。

      1 /**************************************************************
      2     Problem: 3144
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:596 ms
      7     Memory:14056 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <algorithm>
     13  
     14 using namespace std;
     15 const int N = 100005;
     16 const int M = N * 10;
     17 const int inf = 1e9;
     18 const int dx[4] = {0, 0, 1, -1};
     19 const int dy[4] = {1, -1, 0, 0};
     20  
     21 struct edge {
     22   int next, to, f;
     23   edge() {}
     24   edge(int _n, int _t, int _f) : next(_n), to(_t), f(_f) {}
     25 } e[M];
     26  
     27 int first[N], tot = 1;
     28 int n, S, T, P, Q, R, D;
     29 int f[45][45][45];
     30 int d[N], q[N];
     31  
     32 inline int read() {
     33   int x = 0, sgn = 1;
     34   char ch = getchar();
     35   while (ch < '0' || '9' < ch) {
     36     if (ch == '-') sgn = -1;
     37     ch = getchar();
     38   }
     39   while ('0' <= ch && ch <= '9') {
     40     x = x * 10 + ch - '0';
     41     ch = getchar();
     42   }
     43   return sgn * x;
     44 }
     45  
     46 inline void Add_Edges(int x, int y, int z) {
     47   e[++tot] = edge(first[x], y, z), first[x] = tot;
     48   e[++tot] = edge(first[y], x, 0), first[y] = tot;
     49 }
     50  
     51 inline int p(int x, int y, int z) {
     52   return z == 0 ? S : (z - 1) * P * Q + (x - 1) * Q + y;
     53 }
     54  
     55 void build_graph() {
     56   int i ,j, k, l, X, Y;
     57   for (i = 1; i <= P; ++i)
     58     for (j = 1; j <= Q; ++j) {
     59       for (k = 1; k <= R; ++k) {
     60     Add_Edges(p(i, j, k - 1), p(i, j, k), f[i][j][k]);
     61     if (k > D)
     62       for (l = 0; l < 4; ++l) {
     63         X = i + dx[l], Y = j + dy[l];
     64         if (X < 1 || Y < 1 || X > P || Y > Q) continue;
     65         Add_Edges(p(i, j, k), p(X, Y, k - D), inf);
     66       }
     67       }
     68       Add_Edges(p(i, j, R), T, inf);
     69     }
     70 }
     71  
     72 #define y e[x].to
     73 #define p q[l]
     74 bool bfs() {
     75   int l, r, x;
     76   memset(d, -1, sizeof(d));
     77   d[q[1] = S] = 1;
     78   for (l = r = 1; l != r + 1; ++l)
     79     for (x = first[p]; x; x = e[x].next)
     80       if (!~d[y] && e[x].f) {
     81     d[q[++r] = y] = d[p] + 1;
     82     if (y == T) return 1;
     83       }
     84   return 0;
     85 }
     86 #undef p
     87  
     88 int dfs(int p, int lim) {
     89   if (p == T || !lim) return lim;
     90   int x, tmp, rest = lim;
     91   for (x = first[p]; x && rest; x = e[x].next) 
     92     if (d[y] == d[p] + 1 && ((tmp = min(e[x].f, rest)) > 0)) {
     93       rest -= (tmp = dfs(y, tmp));
     94       e[x].f -= tmp, e[x ^ 1].f += tmp;
     95       if (!rest) return lim;
     96     }
     97   if (rest) d[p] = -1;
     98   return lim - rest;
     99 }
    100 #undef y
    101  
    102 int Dinic() {
    103   int res = 0;
    104   while (bfs())
    105     res += dfs(S, inf);
    106   return res;
    107 }
    108  
    109 int main() {
    110   int i, j, k;
    111   P = read(), Q = read(), R = read(), D = read();
    112   S = P * Q * R + 1, T = S + 1;
    113   for (i = 1; i <= R; ++i)
    114     for (j = 1; j <= P; ++j)
    115       for (k = 1; k <= Q; ++k)
    116     f[j][k][i] = read();
    117   build_graph();
    118   printf("%d
    ", Dinic());
    119   return 0;
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    手工给alv添加合计
    双重loop循环时第二个loop用where…
    屏幕的双击事件(如在table&nbsp;c…
    根据CR获取CR下的开发对象
    不在se11建结构smartforms传值方法
    关于SMARTFORM的页数问题
    获取最大权限
    关于oracle的varchar2的比较大小的规律
    oracle中查询、禁用、启用、删除表外键
    关于oracle with as用法(比较简单的介绍)
  • 原文地址:https://www.cnblogs.com/rausen/p/4293877.html
Copyright © 2011-2022 走看看