• P4009 汽车加油行驶问题


    本来想练一手费用流的 但是一看这个题分层图跑的更快 而且也是个很好的分层图板子

    将图分为k+1层 因为充满油可以跑k条边 算上 开始的1 就是k+1层

    首先 第x层图中的点[i,j] 连向第x+1层的点[i,j]的 边权为 0

    如果该点不是加油站 第x层[i,j] 连向第x+1层[i,j+1] [i+1,j]边权为0

                            连向第x+1层[i-1,j] [i,j-1]边权为b
    

    如果设该点为加油站 第x层[i,j] 连向 第1层 [i,j]边权为p+c

    如果该点为加油站 第x层[i,j] 连向 第1层 [i,j] 边权为p

                 第x层[i,j] 连向 第2层 [i,j+1] [i+1,j] 边权为0
                           
                            连向 第2层 [i-1,j] [i,j-1] 边权为b  
    

    注意题目要求遇到油库就要加满油

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int INF=2e9;
    
    int n,k,p,b,c,np;
    int h[350005],ln[350005],q[900005];
    bool vis[350005],oil;
    struct rpg{
    	int li,nx,ln;
    }a[900005];
    
    void add(int x1,int y1,int z1,int x2,int y2,int z2,int ln){
    	int ls=n*n*(z1-1)+(x1-1)*n+y1,nx=n*n*(z2-1)+(x2-1)*n+y2;
    	a[++np]=(rpg){h[ls],nx,ln};
    	h[ls]=np;
    }
    
    void spfa(){
    	for(int i=1;i<=n*n*(k+1);++i) ln[i]=INF;
    	int hd=1,tl=1;
    	q[hd]=1;
    	ln[1]=0;
    	while(hd<=tl){
    		int nw=q[hd++];
    		vis[nw]=0;
    		for(int i=h[nw];i;i=a[i].li){
    			if(ln[a[i].nx]>ln[nw]+a[i].ln){
    				ln[a[i].nx]=ln[nw]+a[i].ln;
    				if(!vis[a[i].nx]){
    					vis[a[i].nx]=1;
    					q[++tl]=a[i].nx;
    				}
    			}
    		}
    	}
    }
    
    int main(){
    	scanf("%d%d%d%d%d",&n,&k,&p,&b,&c);
    	for(int i=1;i<=n;++i){
    		for(int j=1;j<=n;++j){
    			scanf("%d",&oil);
    			for(int l=1;l<=k;++l){
    				add(i,j,l,i,j,l+1,0);
    			}
    			if(oil){
    				for(int l=2;l<=k+1;++l){
    					add(i,j,l,i,j,1,p);
    				}
    				if(i<n) add(i,j,1,i+1,j,2,0);
    				if(j<n) add(i,j,1,i,j+1,2,0);
    				if(i>1) add(i,j,1,i-1,j,2,b);
    				if(j>1) add(i,j,1,i,j-1,2,b);
    			}else{
    				for(int l=1;l<=k;++l){
    					if(i<n) add(i,j,l,i+1,j,l+1,0);
    					if(j<n) add(i,j,l,i,j+1,l+1,0);
    					if(i>1) add(i,j,l,i-1,j,l+1,b);
    					if(j>1) add(i,j,l,i,j-1,l+1,b);
    				}for(int l=2;l<=k+1;++l){
    					add(i,j,l,i,j,1,p+c);
    				}
    			}
    		}
    	}spfa();
    	int ans=INF;
    	for(int i=1;i<=k+1;++i) ans=min(ans,ln[n*n*i]);
    	printf("%d\n",ans);
    	return 0;
    }
  • 相关阅读:
    自动化CodeReview
    10个有关RESTful API良好设计的最佳实践
    ASP.NET Core 获取控制器上的自定义属性
    [转] Autofac创建实例的方法总结
    PetaPoco
    LogViewer
    hdoj:2047
    hdoj:2046
    hdoj:2045
    hdoj:2044
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16133571.html
Copyright © 2020-2023  润新知