• [SCOI2007]蜥蜴


    嘟嘟嘟

     

    这题主要考网络流建图。

    首先每一只蜥蜴像自己所在的石柱连边,然后如果这一只蜥蜴像能跳到的所有石柱连边,那就错了。因为每一只蜥蜴能跳到别的石柱上,然后再跳到更远的石柱上,而上述连边的意思是蜥蜴只能跳到他一步能达到的石柱上。所以,正确的连边应该是以每一个石柱,向能到达的石柱连边,容量为INF。

    题中还有一点:每离开一个石柱,石柱高度减一,这相当于限制了每一个石柱能承受的蜥蜴数量。那么一个常见的做法就是拆点:将每一个石柱拆成跳到他,和从他跳走的,然后连一条容量为石柱高度的边。

    最后就是对于每一个能从他跳出边界的石柱,从他跳走的点向汇点连一条INF的边。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 1205;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, t, d, tot = 0;
     38 
     39 struct Edge
     40 {
     41     int from, to, cap, flow;
     42 };
     43 vector<Edge> edges;
     44 vector<int> G[maxn];
     45 void addEdge(int from, int to, int w)
     46 {
     47     edges.push_back((Edge){from, to, w, 0});
     48     edges.push_back((Edge){to, from, 0, 0});
     49     int sz = edges.size(); 
     50     G[from].push_back(sz - 2);
     51     G[to].push_back(sz - 1);
     52 }
     53 
     54 int dx[20], dy[20], st = 0;
     55 void init(int x)
     56 {
     57     for(int i = -d; i <= d; ++i)
     58         for(int j = -d; j <= d; ++j)
     59             if(i * i + j * j <= d * d) dx[++st] = i, dy[st] = j;
     60 }
     61 
     62 int getnum(int x, int y)
     63 {
     64     return m * (x - 1) + y;
     65 }
     66 
     67 bool judge(int x, int y)
     68 {
     69     if(x + d > n || x - d <= 0 || y + d > m || y - d <= 0) return 1;
     70     return 0;
     71 }
     72 
     73 void add(int x, int y)
     74 {
     75     int u = getnum(x, y) + n * m;
     76     for(int i = 1; i <= st; ++i)
     77     {
     78         int newx = x + dx[i], newy = y + dy[i];
     79         if(newx > 0 && newx <= n && newy > 0 && newy <= m) 
     80             addEdge(u, getnum(newx, newy), INF);
     81     }
     82     
     83 }
     84 
     85 int dis[maxn];
     86 bool bfs()
     87 {
     88     Mem(dis, 0); dis[0] = 1;
     89     queue<int> q; q.push(0);
     90     while(!q.empty())
     91     {
     92         int now = q.front(); q.pop();
     93         for(int i = 0; i < (int)G[now].size(); ++i)
     94         {
     95             Edge& e = edges[G[now][i]];
     96             if(!dis[e.to] && e.cap > e.flow)
     97             {
     98                 dis[e.to] = dis[now] + 1;
     99                 q.push(e.to);
    100             }
    101         }
    102     }
    103     return dis[t];
    104 }
    105 int cur[maxn];
    106 int dfs(int now, int res)
    107 {
    108     if(now == t || res == 0) return res;
    109     int flow = 0, f;
    110     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
    111     {
    112         Edge& e = edges[G[now][i]];
    113         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
    114         {
    115             e.flow += f;
    116             edges[G[now][i] ^ 1].flow -= f;
    117             flow += f;
    118             res -= f;
    119             if(res == 0) break;
    120         }
    121     }
    122     return flow;
    123 }
    124 
    125 int maxflow()
    126 {
    127     int flow = 0;
    128     while(bfs())
    129     {
    130         Mem(cur, 0);
    131         flow += dfs(0, INF);
    132     }
    133     return flow;
    134 }
    135 
    136 char c[25];
    137 
    138 int main()
    139 {
    140     n = read(); m = read(); d = read();
    141     init(d);
    142     t = n * m * 3 + 1;
    143     for(int i = 1; i <= n; ++i)
    144         for(int j = 1; j <= m; ++j)
    145         {
    146             int x; scanf("%1d", &x);
    147             if(x)
    148             {
    149                 int u = getnum(i, j);
    150                 addEdge(u, n * m + u, x);
    151                 if(judge(i, j)) addEdge(n * m + u, t, INF);
    152                 add(i, j);
    153             }
    154         }
    155     for(int i = 1; i <= n; ++i)
    156     {
    157         scanf("%s", c + 1);
    158         for(int j = 1; j <= m; ++j)
    159             if(c[j] == 'L')
    160             {
    161                 tot++;
    162                 int u = getnum(i, j) + ((n * m) << 1);
    163                 addEdge(0, u, 1); 
    164                 addEdge(u, getnum(i, j), 1);
    165             }
    166     }
    167     write(tot - maxflow()); enter;    
    168     return 0;
    169 }
    View Code
  • 相关阅读:
    AOP概述
    AOP-动态代理
    IOC容器和Bean的配置
    Spring框架概述
    异常
    Optional 类
    Stream API
    方法引用(Method References)
    函数式(Functional)接口
    stm8笔记1-搭建工程+孤独的小灯闪烁
  • 原文地址:https://www.cnblogs.com/mrclr/p/9711219.html
Copyright © 2020-2023  润新知