zoukankan      html  css  js  c++  java
  • [bzoj]1066: [SCOI2007]蜥蜴

    原题链接:蜥蜴


    理解很重要,理解很重要,理解很重要!!


    分析:

    看到这题首先可能会想到搜索:裸图??
    但是很明显搜索肯定会超时
    观察题目,发现每根柱子有跳跃次数上限,想到了什么??
    网络流!!
    题目中有坑,每根柱子上只能站一只蜥蜴这个条件其实是没用的。
    因为蜥蜴不动的话对柱子高度是没有影响的,只要按顺序跳跃就行了。
    那么怎么考虑跳跃次数呢?
    可以把每个柱子拆成两个点,一个入点一个出点,从入点到出点有单向流量,流量大小为柱子的高度。
    从超级源向每一个蜥蜴的初始点的入点连流量为1的边。
    每个能跳出去的点向超级汇连流量为无穷大的边。
    再把所有柱子向能跳达的柱子连边,流量为无穷大。
    这样子网络流模型就出来了,我们只需要从源点开始跑一遍最大流,然后拿蜥蜴的总个数减去最大流就是我们的答案了。


    注意!
    第一次写的时候不知道写挂什么了,输出答案一直不对,调错调了一个半小时没有结果,然后重写一遍就对了。所以说如果发现查不出错的话一定要果断重构!!


    下面是代码
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int inf=0x7fffffff;
    int rr,cc,dd,g[25][25],d[5000],s=0,t=1000,mark[25][25];
    int ver[500000],head[5000],next[500000],edge[500000],tot=1;
    queue <int> q;
    void add(int x,int y,int val){
    	ver[++tot]=y;edge[tot]=val;next[tot]=head[x];head[x]=tot;
    	ver[++tot]=x;edge[tot]=0;next[tot]=head[y];head[y]=tot;
    }
    bool judge(int x1,int y1,int x2,int y2){
    	if((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)>dd*dd)return false;
    	else if(g[x1][y1]&&g[x2][y2])return true;
    }
    bool bfs();
    int dinic(int x,int flow);
    int main()
    {
    	//freopen("data.in","r",stdin);
    	char ch[21];
    	int num=0,ans=0,flow,maxflow=0;
    	scanf("%d%d%d",&rr,&cc,&dd);
    	for(int i=1;i<=rr;i++){
    		scanf("%s",ch);
    		for(int j=1;j<=cc;j++){
    			g[i][j]=ch[j-1]-'0';
    			mark[i][j]=++num;
    			if(g[i][j])add(mark[i][j],mark[i][j]+400,g[i][j]);
    		}
    	}
    	for(int i=1;i<=rr;i++){
    		scanf("%s",ch);
    		for(int j=1;j<=cc;j++){
    			if(ch[j-1]=='L'){
    				add(s,mark[i][j],1);
    				ans++;
    			}
    		}
    	}
    	for(int i=1;i<=dd;i++){
    		for(int j=1;j<=cc;j++){
    			add(mark[i][j]+400,t,inf);
    			add(mark[rr-i+1][j]+400,t,inf);
    		}
    	}
    	for(int j=1;j<=dd;j++){
    		for(int i=dd+1;i<=rr-dd;i++){
    			add(mark[i][j]+400,t,inf);
    			add(mark[i][cc-j+1]+400,t,inf);
    		}
    	}
    
    	for(int i=1;i<=rr;i++)
    		for(int j=1;j<=cc;j++)
    			for(int p=(i-dd<=0)?1:i-dd;p<=min(rr,i+dd);p++)
    				for(int q=(j-dd<=0)?1:j-dd;q<=min(cc,j+dd);q++)
    					if(judge(i,j,p,q)&&(i!=p||j!=q))
    						add(mark[i][j]+400,mark[p][q],inf);
        //cout<<1<<endl;
    	while(bfs())
    		while(flow=dinic(s,inf))maxflow+=flow;
    	printf("%d\n",ans-maxflow);
    	return 0;
    }
    bool bfs(){
    	memset(d,0,sizeof(d));
    	while(q.size())q.pop();
    	q.push(s);d[s]=1;
    	while(q.size()){
    		int x=q.front();q.pop();
    		for(int i=head[x];i;i=next[i]){
    			if(edge[i]&&!d[ver[i]]){
    				q.push(ver[i]);
    				d[ver[i]]=d[x]+1;
    				if(ver[i]==t)return true;
    			}
    		}
    	}
    	return false;
    }
    int dinic(int x,int flow){
    	if(x==t)return flow;
    	int res=flow,k;
    	for(int i=head[x];i&&res;i=next[i]){
    		if(edge[i]&&d[ver[i]]==d[x]+1){
    			k=dinic(ver[i],min(flow,edge[i]));
    			if(!k)d[ver[i]]=0;
    			edge[i]-=k;
    			edge[i^1]+=k;
    			res-=k;
    		}
    	}
    	return flow-res;
    }
    
  • 相关阅读:
    tensorflow之tf.squeeze()
    tf.slice()
    tensorflow之tf.meshgrid()
    tensorflow: arg_scope()
    tf.ConfigProto()
    os.path.join()
    argparse.ArgumentParser()用法解析
    Flutter学习之ListView(1)
    Flutter学习之image
    Flutter学习之image
  • 原文地址:https://www.cnblogs.com/onglublog/p/9859683.html
Copyright © 2011-2022 走看看