• [bzoj1066] [SCOI2007]蜥蜴


    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
    

    Solution

    拆点最大流,无脑暴力建边就好了。

    具体的,设(in(x))表示(x)的入点,(out(x))表示出点。

    • 对于有蜥蜴的点(x_i),建(<s,in(x_i),1>)
    • 对于两个距离不超过(d)的点(x,y),建立(<out(x),in(y),infty>)
    • 对于边界的点(x),建立(<out(x),t,infty>)
    • 对于每个点(x),建立(<in(x),out(x),w_x>),其中(w_x)是点权。

    然后我被降智dinic调了一小时

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 2e5+10;
    const int inf = 1e9;
    
    struct edge{int to,nxt,w;}e[maxn];
    int head[maxn],tot=1,n,m,s,t,d,flow,vis[1000],dis[1000],mp[50][50];
    
    void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;}
    void ins(int u,int v,int w) {add(u,v,w),add(v,u,0);}
    	
    int calc(int x,int y,int z) {return (x-1)*m+y+n*m*z;}
     
    #define sqr(x) ((x)*(x))
     
    char ss[maxn];
    
    int bfs() {
    	memset(vis,0,sizeof vis);
    	memset(dis,63,sizeof dis);
    	queue<int > q;q.push(s),dis[s]=0,vis[s]=1;
    	while(!q.empty()) {
    		int now=q.front();q.pop();vis[now]=0;
    		for(int i=head[now];i;i=e[i].nxt)
    			if(e[i].w>0&&dis[e[i].to]>dis[now]+1) {
    				dis[e[i].to]=dis[now]+1;
    				if(!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);
    			}
    	}return dis[t]<inf;
    }
    
    int dfs(int x,int f) {
    	if(x==t||!f) return flow+=f,f;
    	int used=0;
    	for(int i=head[x];i;i=e[i].nxt)
    		if(e[i].w>0&&(x==t||!vis[e[i].to])&&dis[e[i].to]==dis[x]+1) {
    			int dd=dfs(e[i].to,min(f-used,e[i].w));
    			if(dd>0) e[i].w-=dd,e[i^1].w+=dd,used+=dd;
    			if(used==f) break;
    		}return used;
    }
    
    int dinic() {
    	flow=0;while(bfs()) dfs(s,inf);return flow;
    }
    
    int main() {
    	read(n),read(m),read(d);
    	s=n*m*2+3,t=n*m*2+4;
    	for(int i=1;i<=n;i++) {
    		scanf("%s",ss+1);
    		for(int j=1;j<=m;j++) ins(calc(i,j,0),calc(i,j,1),ss[j]-'0'),mp[i][j]=(ss[j]>'0');
    	}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			for(int a=1;a<=n;a++)
    				for(int b=1;b<=m;b++)
    					if(mp[a][b]&&mp[i][j]&&sqr(a-i)+sqr(b-j)<=sqr(d))
    						ins(calc(i,j,1),calc(a,b,0),inf);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(min(min(i,n-i+1),min(j,m-j+1))<=d) ins(calc(i,j,1),t,inf);
    	int cnt=0;
    	for(int i=1;i<=n;i++) {
    		scanf("%s",ss+1);
    		for(int j=1;j<=m;j++) if(ss[j]=='L') ins(s,calc(i,j,0),1),cnt++;
    	}
    	write(cnt-dinic());
    	return 0;
    }
    
  • 相关阅读:
    SQLite(快速上手版)笔记
    自定义带图片和文字的ImageTextButton
    Android 网络连接判断与处理
    Android轻量缓存框架--ASimpleCache
    Mvc4_ActionLink跟@RenderBody ,@RenderPage
    Mvc4_传值取值应用
    Mvc4_ActionResult应用
    IIS_Mvc发布
    IIS_各种问题
    SqlServer_事务
  • 原文地址:https://www.cnblogs.com/hbyer/p/10413796.html
Copyright © 2020-2023  润新知