• [TJOI2009] 战争游戏


    题目背景

    小R正在玩一个战争游戏。游戏地图是一个M行N列的矩阵,每个格子可能是障碍物,也可能是空地,在游戏开始时有若干支敌军分散在不同的空地格子中。每支敌军都可以从当前所在的格子移动到四个相邻的格子之一,但是不能移动到包含障碍物的格子。如果敌军移动出了地图的边界,那么战争就失败了。

    题目描述

    现在你的任务是,在敌军开始移动前,通过飞机轰炸使得某些原本是空地的格子变得不可通行,这样就有可能阻止敌军移出地图边界(出于某种特殊的考虑,你不能直接轰炸敌军所在的格子)。由于地形不同的原因,把每个空地格子轰炸成不可通行所需的xx数目可能是不同的,你需要计算出要阻止敌军所需的最少的xx数。

    输入输出格式

    输入格式:

    输入文件的第一行包含两个数M和N,分别表示矩阵的长和宽。接下来M行,每行包含用空格隔开的N个数字,每个数字表示一个格子的情况:若数字为-1,表示这个格子是障碍物;若数字为0,表示这个格子里有一支敌军;若数字为一个正数x,表示这个格子是空地,且把它轰炸成不可通行所需的xx数为x。

    输出格式:

    输出一个数字,表示所需的最少xx数。数据保证有解存在。

    输入输出样例

    输入样例#1: 
    4 3
    1 2 1
    1 10 1
    1 0 -1
    1 1 1
    输出样例#1: 
    6

    说明

    对50%的数据,1 ≤ M,N ≤ 10

    对100%的数据,1 ≤ M,N ≤ 30

    矩阵里的每个数不超过100

        最小割套路题,拆点限流量,把0看成源,相邻的点之间连边,边界的点向汇连边,最小割就是答案。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1805;
    #define pb push_back
    const int inf=1<<30;
    vector<int> g[maxn];
    struct lines{
    	int to,flow,cap;
    }l[maxn*233];
    int S,t=-1,T,d[maxn],cur[maxn];
    bool v[maxn];
    
    inline void add(int from,int to,int cap){
    	l[++t]=(lines){to,0,cap},g[from].pb(t);
    	l[++t]=(lines){from,0,0},g[to].pb(t);
    }
    
    inline bool BFS(){
    	memset(v,0,sizeof(v));
    	queue<int> q; q.push(S);
    	v[S]=1,d[S]=0;
    	int x; lines e;
    	
    	while(!q.empty()){
    		x=q.front(),q.pop();
    		for(int i=g[x].size()-1;i>=0;i--){
    			e=l[g[x][i]];
    			if(e.flow<e.cap&&!v[e.to]) v[e.to]=1,d[e.to]=d[x]+1,q.push(e.to);
    		}
    	}
    	
    	return v[T];
    }
    
    int dfs(int x,int A){
    	if(x==T||!A) return A;
    	int flow=0,f,sz=g[x].size();
    	for(int &i=cur[x];i<sz;i++){
    		lines &e=l[g[x][i]];
    		if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(A,e.cap-e.flow)))){
    			A-=f,flow+=f;
    			e.flow+=f,l[g[x][i]^1].flow-=f;
    			if(!A) break;
    		}
    	}
    	
    	return flow;
    }
    
    inline int max_flow(){
    	int an=0;
    	while(BFS()){
    		memset(cur,0,sizeof(cur));
    		an+=dfs(S,inf);
    	}
    	return an;
    }
    
    int n,m,id[233][233],cnt=0,a[233][233];
    int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    
    inline void build(){
    	for(int i=1;i<=n;i++)
    	    for(int j=1;j<=m;j++) if(a[i][j]>0) id[i][j]=++cnt;
    	    
    	S=0,T=cnt*2+1;
    	
    	for(int i=1;i<=n;i++)
    	    for(int j=1;j<=m;j++) if(a[i][j]>=0){
    	    	if(a[i][j]>0){
    			    add(id[i][j],id[i][j]+cnt,a[i][j]);
    	    	    if(i==1||i==n||j==1||j==m) add(id[i][j]+cnt,T,inf);
    	    	}
    	    	
    	    	for(int o=0,x,y;o<4;o++){
    	    		x=i+dx[o],y=j+dy[o];
    	    		if(x&&x<=n&&y&&y<=m&&id[x][y]) add(a[i][j]?id[i][j]+cnt:S,id[x][y],inf);
    			}
    		}
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	    for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
    	
    	build();
    	printf("%d
    ",max_flow());
    	
    	return 0;
    }
    

      

  • 相关阅读:
    [置顶] windows player,wzplayerV2 for windows
    wzplayer 近期将会支持BlackBerry和WinPhone8
    wzplayerEx for android(真正硬解接口,支持加密的 player)
    ffmpeg for ios 交叉编译 (支持i686 armv7 armv7s) 包含lame支持
    ffmpeg for ios 交叉编译 (支持i686 armv7 armv7s) 包含lame支持
    编译cegcc 0.59.1
    wzplayer 近期将会支持BlackBerry和WinPhone8
    wzplayerEx for android(真正硬解接口,支持加密的 player)
    windows player,wzplayerV2 for windows(20140416)更新
    编译cegcc 0.59.1
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9073460.html
Copyright © 2020-2023  润新知