• [HDOJ3657]Game


    方格取数问题,最小割模型~

    View Code
    1 #include <cstdio>
    2 #include <cstring>
    3
    4  using namespace std;
    5
    6  const int maxN = 64;
    7 const int INF = (1 << 30);
    8 const int dx[] = { -1, 0, 1, 0 };
    9 const int dy[] = { 0, 1, 0, -1 };
    10
    11 class Network {
    12 private:
    13 const static int MAXV = 10240; // ¶¥µãÊý
    14 const static int MAXE = 100000; // ±ßÊý * 2
    15
    16 struct List {
    17 int v;
    18 int f;
    19 List * rev;
    20 List * next;
    21 };
    22
    23 List pool[MAXE];
    24 List * path[MAXV];
    25 List * head[MAXV];
    26 List * cur[MAXV];
    27 List * pp;
    28
    29 int n;
    30 int s;
    31 int t;
    32 int dist[MAXV];
    33 int num[MAXV];
    34 int pred[MAXV];
    35
    36 inline List * create(int v, int f, List * next) {
    37 pp->v = v;
    38 pp->f = f;
    39 pp->next = next;
    40 return pp++;
    41 }
    42
    43 void InitDist();
    44 int Augment(int &);
    45 public:
    46 void Init(int nv, int ss, int tt);
    47 void addEdge(int u, int v, int f);
    48 int maxFlow();
    49 };
    50
    51 void Network::Init(int nv, int ss, int tt) {
    52 int i;
    53
    54 n = nv;
    55 s = ss;
    56 t = tt;
    57
    58 pp = pool;
    59 memset(head, 0, n * sizeof(head[0]));
    60 memset(cur, 0, n * sizeof(cur[0]));
    61 memset(num, 0, n * sizeof(int));
    62
    63 pred[s] = -1;
    64
    65 for (i = 0; i < n; i++)
    66 dist[i] = n;
    67
    68 return;
    69 }
    70
    71 void Network::addEdge(int u, int v, int f) {
    72 head[u] = create(v, f, head[u]);
    73 head[v] = create(u, 0, head[v]);
    74
    75 head[u]->rev = head[v];
    76 head[v]->rev = head[u];
    77
    78 return;
    79 }
    80
    81 void Network::InitDist() {
    82 int queue[MAXV];
    83 int qh = -1;
    84 int qe = 0;
    85
    86 List * p;
    87
    88 dist[t] = 0;
    89 queue[0] = t;
    90
    91 while (qh != qe) {
    92 qh++;
    93 int u = queue[qh];
    94 for (p = head[u]; p; p = p->next)
    95 if (p->f == 0 && dist[p->v] == n) {
    96 dist[p->v] = dist[u] + 1;
    97 num[dist[p->v]]++;
    98 queue[++qe] = p->v;
    99 }
    100 }
    101
    102 return;
    103 }
    104
    105 int Network::Augment(int & sum) {
    106 int u;
    107 int last = s;
    108 int minl = INF;
    109
    110 for (u = t; u != s; u = pred[u])
    111 minl = minl < path[u]->f ? minl : path[u]->f;
    112 sum += minl;
    113 for (u = t; u != s; u = pred[u]) {
    114 path[u]->f -= minl;
    115 path[u]->rev->f += minl;
    116 if (path[u]->f == 0)
    117 last = pred[u];
    118 }
    119
    120 return last;
    121 }
    122
    123 int Network::maxFlow() {
    124 bool update;
    125 int u = s;
    126 int ret = 0;
    127
    128 List * p;
    129
    130 InitDist();
    131 memcpy(cur, head, sizeof(head));
    132
    133 while (dist[s] < n) {
    134 update = false;
    135 for (p = cur[u]; p; p = p->next)
    136 if (dist[p->v] + 1 == dist[u] && p->f > 0) {
    137 update = true;
    138 pred[p->v] = u;
    139 path[p->v] = p;
    140 cur[u] = p;
    141 u = p->v; // Ç°œø²œ
    142 if (u == t)
    143 u = Augment(ret);
    144 break;
    145 }
    146 if (!update) {
    147 if (--num[dist[u]] == 0) // Œä϶ÓÅ»¯
    148 break;
    149 cur[u] = head[u];
    150 dist[u] = n;
    151 for (p = head[u]; p; p = p->next) // ÖرêºÅ
    152 if (p->f > 0 && dist[u] > dist[p->v] + 1)
    153 dist[u] = dist[p->v] + 1;
    154 if (dist[u] < n)
    155 num[dist[u]]++;
    156 if (u != s) // »ØÍ˲œ
    157 u = pred[u];
    158 }
    159 }
    160 return ret;
    161 }
    162
    163 Network net;
    164
    165 int maze[maxN][maxN];
    166 bool must[maxN][maxN];
    167
    168 int main() {
    169 int nr;
    170 int nc;
    171 int nk;
    172 int sum;
    173
    174 while (scanf("%d %d %d", &nr, &nc, &nk) != EOF) {
    175 sum = 0;
    176 memset(must, false, sizeof(must));
    177 for (int i = 0; i < nr; i++) {
    178 for (int j = 0; j < nc; j++) {
    179 scanf("%d", &maze[i][j]);
    180 sum += maze[i][j];
    181 }
    182 }
    183 for (int i = 0; i < nk; i++) {
    184 int x, y;
    185 scanf("%d %d", &x, &y);
    186 must[x - 1][y - 1] = true;
    187 }
    188
    189 net.Init(nr * nc + 2, 0, nr * nc + 1);
    190 for (int i = 0; i < nr; i++) {
    191 for (int j = 0; j < nc; j++) {
    192 if ((i + j) & 1) {
    193 net.addEdge(0, i * nc + j + 1, must[i][j] ? INF : maze[i][j]);
    194 for (int k = 0; k < 4; k++) {
    195 int ni = i + dx[k];
    196 int nj = j + dy[k];
    197 if (ni >= 0 && ni < nr && nj >= 0 && nj < nc) {
    198 net.addEdge(i * nc + j + 1, ni * nc + nj + 1, 2
    199 * (maze[i][j] & maze[ni][nj]));
    200 }
    201 }
    202 } else {
    203 net.addEdge(i * nc + j + 1, nr * nc + 1, must[i][j] ? INF : maze[i][j]);
    204 }
    205 }
    206 }
    207
    208 int maxFlow = net.maxFlow();
    209 printf("%d\n", sum - maxFlow);
    210 }
    211 return 0;
    212 }
  • 相关阅读:
    黑马程序员_网络编程
    黑马程序员_ 异常
    黑马程序员_面向对象基础
    黑马程序员_循环语句的使用
    黑马程序员_面向对象深入2
    黑马程序员_ JAVA中的多线程
    黑马程序员_JAVA基础知识总结3
    OC-内存管理
    OC-核心语法(3)(分类、SEL、类本质)
    OC-核心语法2-构造方法
  • 原文地址:https://www.cnblogs.com/debugcool/p/HDOJ3657.html
Copyright © 2020-2023  润新知