• BZOJ1066: [SCOI2007]蜥蜴


    1066: [SCOI2007]蜥蜴

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 4506  Solved: 2305
    [Submit][Status][Discuss]

    Description

      在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃
    到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石
    柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不
    变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个
    石柱上。

    Input

      输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱
    ,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

    Output

      输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

    Sample Input

    5 8 2
    00000000
    02000000
    00321100
    02000000
    00000000
    ........
    ........
    ..LLLL..
    ........
    ........

    Sample Output

    1

    HINT

    100%的数据满足:1<=r, c<=20, 1<=d<=4

    Source

    【题解】

    此题每个点有流量限制,可以考虑拆点。

    点x拆成x和x'。

    有蜥蜴的点x,从S连向x,容量为1

    能跳到外部的点x,从x'连向T,容量为INF

    能彼此到达的点x,y,从x'连向y,从y'连向x,容量为INF,这样从x走向y,必须先从x走向x'再走向y,限制了点x的流量

    然后从x连向x',容量为点x的流量限制

    挂了好多细节

    写题要专心,一不专心就挂细节

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 #define min(a, b) ((a) < (b) ? (a) : (b))
     10 #define max(a, b) ((a) > (b) ? (a) : (b))
     11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
     12 inline void swap(int &a, int &b)
     13 {
     14     long long tmp = a;a = b;b = tmp;
     15 }
     16 inline void read(int &x)
     17 {
     18     x = 0;char ch = getchar(), c = ch;
     19     while(ch < '0' || ch > '9') c = ch, ch = getchar();
     20     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
     21     if(c == '-')x = -x;
     22 }
     23 
     24 const int INF = 0x3f3f3f3f;
     25 const int MAXN = 500;
     26 const int MAXM = 2000000;
     27 
     28 struct Edge
     29 {
     30     int u,v,w,nxt;
     31     Edge(int _u, int _v, int _w, int _nxt){u = _u;v = _v;w = _w;nxt = _nxt;}
     32     Edge(){}
     33 }edge[MAXM << 1];
     34 int head[200000], cnt = 1, q[200000], h[200000], ans = 0, S, T;
     35 
     36 inline void insert(int a, int b, int c)
     37 {
     38     edge[++cnt] = Edge(a,b,c,head[a]);
     39     head[a] = cnt;
     40     edge[++cnt] = Edge(b,a,0,head[b]);
     41     head[b] = cnt;
     42 }
     43 
     44 bool bfs()
     45 {
     46     int he = 0, ta = 1;
     47     memset(h, -1, sizeof(h));
     48     q[he] = S, h[S] = 0;
     49     while(he < ta)
     50     {
     51         int now = q[he ++];
     52         for(int pos = head[now];pos;pos = edge[pos].nxt)
     53         {
     54             int v = edge[pos].v;
     55             if(h[v] == -1 && edge[pos].w)
     56             {
     57                 h[v] = h[now] + 1;
     58                 q[ta ++] = v;
     59             }
     60         }
     61     }
     62     return h[T] != -1;
     63 }
     64 
     65 int dfs(int x, int f)
     66 {
     67     if(x == T) return f;
     68     int w, used = 0;
     69     for(int pos = head[x];pos;pos = edge[pos].nxt)
     70     {
     71         int v = edge[pos].v;
     72         if(h[v] == h[x] + 1)
     73         {
     74             w = dfs(v, min(f - used, edge[pos].w));
     75             edge[pos].w -= w;
     76             edge[pos ^ 1].w += w;
     77             used += w;
     78             if(used == f) return f;
     79         }
     80     }
     81     if(!used) h[x] = -1;
     82     return used;
     83 }
     84 
     85 void dinic()
     86 {
     87     while(bfs()) ans += dfs(S, INF);
     88 }
     89 
     90 int r,c,d,g[MAXN][MAXN],x[MAXN << 1],y[MAXN << 1],w[MAXN << 1],tot,t;
     91 char s[MAXN][MAXN];
     92 
     93 int main()
     94 {
     95     S = 100000, T = 100001;
     96     read(r), read(c), read(d);
     97     for(register int i = 1;i <= r;++ i)
     98     {
     99         scanf("%s", s[i] + 1);
    100         for(register int j = 1;j <= c;++ j)
    101             g[i][j] = s[i][j] - '0';
    102     }
    103     for(register int i = 1;i <= r;++ i)
    104         scanf("%s", s[i] + 1);
    105     for(register int i = 1;i <= r;++ i)
    106         for(register int j = 1;j <= c;++ j)
    107         {
    108             if(s[i][j] == 'L') ++ t;
    109             if(g[i][j] > 0)
    110             {
    111                 ++ tot;x[tot] = i, y[tot] = j, w[tot] = g[i][j];
    112             }
    113         } 
    114     for(register int i = 1;i <= tot;++ i)
    115     {
    116         int tmp = min(x[i], min(y[i], min(r - x[i] + 1, c - y[i] + 1)));
    117         if(tmp <= d) 
    118             insert(i + tot, T, INF);
    119         if(s[x[i]][y[i]] == 'L') 
    120             insert(S, i, 1);
    121         insert(i, i + tot, w[i]);
    122     }
    123     for(register int i = 1;i <= tot;++ i)
    124         for(register int j = i + 1;j <= tot;++ j)
    125         {
    126             if((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]) <= d * d)
    127                 insert(i + tot, j, INF), insert(j + tot, i, INF);
    128         }
    129     dinic();
    130     printf("%d", t - ans);
    131     return 0;
    132 }
    BZOJ1066
  • 相关阅读:
    G面经prepare: Maximum Subsequence in Another String's Order
    G面经prepare: Set Intersection && Set Difference
    G面经prepare: Pattern Match
    G面经prepare: Data Stream Average
    Summary: Final Keyword
    G面经prepare: Android Phone Unlock Pattern
    G面经prepare: Jump Game Return to Original Place
    G面经prepare: Reorder String to make duplicates not consecutive
    G面经prepare: Sort String Based On Another
    G面经Prepare: Valid Preorder traversal serialized String
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8284484.html
Copyright © 2020-2023  润新知