• UVa 1515


    题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=4261&mosmsg=Submission+received+with+ID+26560200

    首先将边缘的洞全部填成草,然后从源点向草连容量为 (d) 的边,表示将草变为洞需要 (d) 的代价,

    从洞向汇点连容量为 (f) 的边,表示将洞变成草需要 (f) 的代价,

    相邻的格子互相连容量为 (b) 的边,表示如果一个为草,一个为洞,建立栅栏需要 (b) 的代价

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 2555;
    const int INF = 1000000007;
    
    int T, n, m, ans;
    int D, F, B;
    int mat[101][101];
    
    int h[maxn], cnt = 1;
    struct E{
    	int to, cap, next;
    }e[1000100];
    void add(int u, int v, int c){
    	e[++cnt].to = v;
    	e[cnt].cap = c;
    	e[cnt].next = h[u];
    	h[u] = cnt;
    	
    	e[++cnt].to = u;
    	e[cnt].cap = 0;
    	e[cnt].next = h[v];
    	h[v] = cnt;
    }
    
    int s,t;
    int vis[maxn], d[maxn], cur[maxn];
    
      bool BFS() {
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s);
        vis[s] = 1;
        d[s] = 0;
        while(!Q.empty()) {
          int u = Q.front(); Q.pop();
          for(int i = h[u]; i != -1 ; i = e[i].next) {
            if(!vis[e[i].to] && e[i].cap) {
              vis[e[i].to] = 1;
              d[e[i].to] = d[u] + 1;
              Q.push(e[i].to);
            }
          }
        }
        return vis[t];
      }
    
      int DFS(int x, int a) {
        if(x == t || a == 0) return a;
        int flow = 0, f;
        for(int &i = cur[x]; i != -1 ; i = e[i].next) {
          if(d[x] + 1 == d[e[i].to] && (f = DFS(e[i].to, min(a, e[i].cap))) > 0) {
            e[i].cap -= f;
            e[i^1].cap += f;
            flow += f;
            a -= f;
            if(a == 0) break;
          }
        }
        return flow;
      }
    
      int Maxflow() {
        int flow = 0;
        while(BFS()) {
    	  memcpy(cur, h, sizeof(h));
          flow += DFS(s, INF);
        }
        return flow;
      }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    inline int ID(int i, int j) { return (i-1)*m+j; }
    
    int main(){
    	scanf("%d", &T);
    	while(T--){
    		memset(h, -1, sizeof(h)); cnt = 1;
    		ans = 0;
    		
    		scanf("%d%d", &m, &n);
    		scanf("%d%d%d", &D, &F, &B);
    		
    		char ss[100];
    		for(int i = 1 ; i <= n ; ++i){
    			scanf("%s", ss + 1);
    			for(int j = 1 ; j <= m ; ++j){
    				if(ss[j] == '.') mat[i][j] = 1;
    				else mat[i][j] = 0;
    			}
    		}
    		
    		for(int i = 1 ; i <= n ; ++i){
    			for(int j = 1 ; j <= m ; ++j){
    				if((i == 1 || i == n || j == 1 || j == m) && (mat[i][j] == 1)){	// 边缘的洞都填成草
    					mat[i][j] = 0;
    					ans += F;
    				}
    			}
    		}
    		
    		s = n * m + 1; t = n * m + 2;
    		for(int i = 1 ; i <= n ; ++i){
    			for(int j = 1 ; j <= m ; ++j){
    				if(!mat[i][j]){ // 源点 -> 草 
    					int C;
    					if(i == 1 || i == n || j == 1 || j == m) C = INF;
    					else C = D;
    					add(s, ID(i, j), C);
    				} else{ // 洞 -> 汇点 
    					add(ID(i, j), t, F);
    				}
    				
    				// 相邻的边相互连接 
    				
    				if(i > 1) {
    					add(ID(i,j), ID(i-1,j), B);
    				} 
            		if(i < n) {
            			add(ID(i,j), ID(i+1,j), B);
    				}
            		if(j > 1) {
            			add(ID(i,j), ID(i,j-1), B);
    				}
            		if(j < m) {
            			add(ID(i,j), ID(i,j+1), B);
    				}
    			}
    		}
    		
    		ans += Maxflow();
    		
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    棋盘型动态规划 之 CODE[VS] 1220 数字三角形
    棋盘型动态规划 之 CODE[VS] 1219 骑士游历 1997年
    棋盘型动态规划 之 CODE[VS] 1169 传纸条 2008年NOIP全国联赛提高组
    棋盘型动态规划 之 CODE[VS] 1010 过河卒 2002年NOIP全国联赛普及组
    [实验]自举?只不过是电容和二极管捣的乱
    [嵌入式]I2C协议指东
    [语法]C语言中二维数组做输入参数
    深入类方法。
    今天周六祝大家休息开心,我还在奋斗....
    我们一起来一把.....现在学习真的好累,一天下来脑袋要炸
  • 原文地址:https://www.cnblogs.com/tuchen/p/14998601.html
Copyright © 2020-2023  润新知