zoukankan      html  css  js  c++  java
  • bzoj4213 贪吃蛇

    题意:给定网格图,有障碍。

    你要用若干条蛇把所有空地覆盖起来。

    满足:每条蛇要么成环,要么头尾都在边界。

    如果一条蛇同时满足,那么算成环。

    要使头尾都在边界的蛇最少。

    解:

    一开始想用一个流量代表一条蛇,顺着这个思路想了很久都没想出来。最后终于看了题解。

    如果把蛇看做边,那么每个空地都要和旁边两个空地相连。或者在边界。

    然后我们又可以黑白染色一波。

    这样的话,我们指定流量从白到黑,那么每个白色就应该获得两个流量以便流出去,而每个黑的要接受两个流量。

    所以从s向白连流量限制为[2, 2]的边,黑色向t同样。

    白向相邻黑连流量限制[0, 1]的边。

    边界怎么处理?白向t连[0, 1],费用为1的边。s向黑同样。

    然后求有源汇有上下界最小费用可行流即可。

    输出答案时要/2,因为头尾各算了一次。

      1 /**************************************************************
      2     Problem: 4213
      3     Language: C++
      4     Result: Accepted
      5     Time:144 ms
      6     Memory:32128 kb
      7 ****************************************************************/
      8  
      9 #include <cstdio>
     10 #include <algorithm>
     11 #include <queue>
     12 #include <cstring>
     13 #include <string>
     14  
     15 const int N = 1000, M = 1000010, INF = 0x3f3f3f3f;
     16 const int dx[] = {0, 1, 0, -1};
     17 const int dy[] = {1, 0, -1, 0};
     18  
     19 struct Edge {
     20     int nex, v, c, len;
     21 }edge[M << 1]; int top = 1;
     22  
     23 int e[N], d[N], vis[N], pre[N], flow[N], G[20][20], m, n, lm, ot[N];
     24 std::queue<int> Q;
     25 char str[20];
     26  
     27 inline void add(int x, int y, int z, int w) {
     28     top++;
     29     edge[top].v = y;
     30     edge[top].c = z;
     31     edge[top].len = w;
     32     edge[top].nex = e[x];
     33     e[x] = top;
     34  
     35     top++;
     36     edge[top].v = x;
     37     edge[top].c = 0;
     38     edge[top].len = -w;
     39     edge[top].nex = e[y];
     40     e[y] = top;
     41     return;
     42 }
     43  
     44 inline bool SPFA(int s, int t) {
     45     memset(d, 0x3f, sizeof(d));
     46     d[s] = 0;
     47     flow[s] = INF;
     48     vis[s] = 1;
     49     Q.push(s);
     50     while(!Q.empty()) {
     51         int x = Q.front();
     52         Q.pop();
     53         vis[x] = 0;
     54         for(int i = e[x]; i; i = edge[i].nex) {
     55             int y = edge[i].v;
     56             if(edge[i].c && d[y] > d[x] + edge[i].len) {
     57                 d[y] = d[x] + edge[i].len;
     58                 pre[y] = i;
     59                 flow[y] = std::min(flow[x], edge[i].c);
     60                 if(!vis[y]) {
     61                     vis[y] = 1;
     62                     Q.push(y);
     63                 }
     64             }
     65         }
     66     }
     67     return d[t] < INF;
     68 }
     69  
     70 inline void update(int s, int t) {
     71     int temp = flow[t];
     72     while(t != s) {
     73         int i = pre[t];
     74         edge[i].c -= temp;
     75         edge[i ^ 1].c += temp;
     76         t = edge[i ^ 1].v;
     77     }
     78     return;
     79 }
     80  
     81 inline int solve(int s, int t, int &cost) {
     82     int ans = 0;
     83     cost = 0;
     84     while(SPFA(s, t)) {
     85         ans += flow[t];
     86         cost += flow[t] * d[t];
     87         update(s, t);
     88     }
     89     return ans;
     90 }
     91  
     92 inline int id(int x, int y, int f = 0) {
     93     int ans = (x - 1) * m + y;
     94     return ans;
     95 }
     96  
     97 inline void judge(int x) {
     98     for(int i = e[x]; i; i = edge[i].nex) {
     99         if(edge[i].c) {
    100             printf("ss -> %d  c = %d 
    ", edge[i].v, edge[i].c);
    101         }
    102     }
    103     return;
    104 }
    105  
    106 int main() {
    107  
    108     int i = 0, sum = 0;
    109     while(scanf("%s", str + 1) != EOF) {
    110         i++;
    111         m = strlen(str + 1);
    112         for(int j = 1; j <= m; j++) {
    113             G[i][j] = (str[j] == '#');
    114         }
    115     }
    116     n = i;
    117     lm = n * m;
    118     int s = lm + 1, t = lm + 2, ss = lm + 3, tt = lm + 4;
    119     for(i = 1; i <= n; i++) {
    120         for(int j = 1; j <= m; j++) {
    121             if(G[i][j]) {
    122                 continue;
    123             }
    124             if((i + j) & 1) {
    125                 // s - 2 > (i, j)
    126                 add(ss, id(i, j), 2, 0);
    127                 sum += 2;
    128                 ot[s] += 2;
    129                 for(int k = 0; k < 4; k++) {
    130                     int x = i + dx[k];
    131                     int y = j + dy[k];
    132                     if(x && y && x <= n && y <= m && !G[x][y]) {
    133                         add(id(i, j), id(x, y), 1, 0);
    134                     }
    135                 }
    136                 if(i == 1 || j == 1 || i == n || j == m) {
    137                     add(id(i, j), t, 1, 1);
    138                 }
    139             }
    140             else {
    141                 // (i, j) - 2 > t
    142                 add(id(i, j), tt, 2, 0);
    143                 ot[t] -= 2;
    144                 if(i == 1 || j == 1 || i == n || j == m) {
    145                     add(s, id(i, j), 1, 1);
    146                 }
    147             }
    148  
    149         }
    150     }
    151     add(s, tt, ot[s], 0);
    152     add(ss, t, -ot[t], 0);
    153     add(t, s, INF, 0);
    154     sum += -ot[t];
    155     int ans;
    156  
    157     if(solve(ss, tt, ans) != sum) {
    158         puts("-1");
    159         return 0;
    160     }
    161     printf("%d", ans / 2);
    162     return 0;
    163 }
    AC代码

    hzwer巨佬写了个随机排列起点然后贪心的乱搞,居然有70pts+ %%%

  • 相关阅读:
    Java_io_02_从一个目录拷贝文件到另一个目录下
    JavaUtil_02_二维码的生成与解析
    Oracle_Exception_01_The Network Adapter could not establish the connection
    Linux_笔记_01_设置静态IP与 SecureCRT连接Linux
    Mybatis_笔记_01_逆向工程
    Java企业微信开发_Exception_02_java.security.InvalidKeyException: Illegal key size
    Java_总结_00_资源贴
    Java企业微信开发_06_素材管理之上传本地临时素材文件至微信服务器
    Java企业微信开发_05_消息推送之被动回复消息
    Java企业微信开发_04_消息推送之发送消息(主动)
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10099420.html
Copyright © 2011-2022 走看看