zoukankan      html  css  js  c++  java
  • 【线性规划与网络流24题】汽车加油行驶问题 分层图

    汽车加油行驶问题

    Time Limit: 1 Sec  Memory Limit: 128 MB

    Description

    给定一个 N*N的方形网格,设其左上角为起点◎,坐标为( 1,1),X轴向右为正, Y轴向下为正,每一个方格边长为 1,如图所看到的。一辆汽车从起点◎出发驶向右下角终点▲,其坐标为( N,N)。在若干个网格交叉点处,设置了油库,可供汽车在行驶途中加油。汽车在行驶过程中应遵守例如以下规则: 
    (1)汽车仅仅能沿网格边行驶,装满油后能行驶 K条网格边。出发时汽车已装满油,在起点与终点处不设油库。 
    (2)汽车经过一条网格边时,若其 X坐标或 Y坐标减小,则应付费用 B,否则免付费用。 
    (3)汽车在行驶过程中遇油库则应加满油并付加油费用 A。 
    (4)在须要时可在网格点处增设油库,并付增设油库费用 C(不含加油费用 A)。 
    (5)(1)~(4)中的各数 N、K、A、B、C均为正整数,且满足约束:2 ≤ N ≤ 100,2 ≤ K ≤ 10。设计一个算法,求出汽车从起点出发到达终点的一条所付费用最少的行驶路线。 

    对于给定的交通网格,计算汽车从起点出发到达终点的一条所付费用最少的行驶路线。 

    Input

    文件的第一行是 N,K,A,B,C的值。第二行起是一个 N*N的 0-1方阵,每行 N个值,至 N+1行结束。方阵的第 i行第 j列处的值为 1表示在网格交叉点( i,j)处设置了一个油库,为 0时表示未设油库。各行相邻两个数以空格分隔。 

    Output

    输出最小费用

    Sample Input

    9 3 2 3 60 0 0 0 1 0 0 0 00 0 0 1 0 1 1 0 01 0 1 0 0 0 0 1 00 0 0 0 0 1 0 0 11 0 0 1 0 0 1 0 00 1 0 0 0 0 0 1 00 0 0 0 1 0 0 0 11 0 0 1 0 0 0 1 00 1 0 0 0 0 0 0 0

    Sample Output

    12

    Source


        题意依旧不加赘述,题解也不难说,就是比裸最短路多几种转移方式,我不说转移方程了,代码写得非常美丽。

        1 . 依据方向的不同要有一个费用B。

        2 . 加油站问题,即能够把油量转移成满,注意用不用建就可以。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 105
    #define K 15
    #define inf 0x3f3f3f3f
    using namespace std;
    const int dx[4]={1,0,-1,0};
    const int dy[4]={0,1,0,-1};
    struct Lux
    {
    	int k,x,y;
    	Lux(int a,int b,int c):k(a),x(b),y(c){}
    	Lux(){}
    };
    
    int map[N][N],id[N][N],cnt;
    int n,p,A,B,C;
    int dist[K][N][N];
    bool in[K][N][N];
    Lux s,t;
    
    int spfa()
    {
    	int i,vx,vy,fee,fee2;
    	queue<Lux>q;
    	memset(dist,0x3f,sizeof(dist));
    	dist[s.k][s.x][s.y]=0;
    	in[s.k][s.x][s.y]=1;
    	q.push(s);
    	while(!q.empty())
    	{
    		Lux U=q.front();q.pop();in[U.k][U.x][U.y]=0;
    		if(!U.k)continue;//没油了还跑什么
    		for(fee=i=0;i<4;i++)
    		{
    			vx=U.x+dx[i];
    			vy=U.y+dy[i];
    			if(i==2)fee=B;/*往回走要多付的费用在这里处理了。*/
    			if(!id[vx][vy])continue;
    			if(!map[vx][vy])
    			{
    				fee2=C;/*新开油站,准确的说这里的思想是把全图都开成加油站,原加油站强制加油,新加油站不强制,但加油要多付钱*/
    				if(U.k&&dist[U.k-1][vx][vy]>dist[U.k][U.x][U.y]+fee)
    				{/*由于加油站强制加油,所以不是加油站才干这么转移。*/
    					dist[U.k-1][vx][vy]=dist[U.k][U.x][U.y]+fee;
    					if(!in[U.k-1][vx][vy])in[U.k-1][vx][vy]=1,q.push(Lux(U.k-1,vx,vy));
    				}
    			}
    			else fee2=0;/*已经有原加油站了就不须要再付额外费用了*/
    			
    			if(dist[p][vx][vy]>dist[U.k][U.x][U.y]+A+fee+fee2)
    			{/*加油的转移*/
    				dist[p][vx][vy]=dist[U.k][U.x][U.y]+A+fee+fee2;
    				if(!in[p][vx][vy])in[p][vx][vy]=1,q.push(Lux(p,vx,vy));
    			}
    		}
    	}
    	int ret=inf;
    	for(i=0;i<=p;i++)ret=min(ret,dist[i][t.x][t.y]);
    	return ret;
    }
    
    int main()
    {
    //	freopen("test.in","r",stdin);
    	scanf("%d%d%d%d%d",&n,&p,&A,&B,&C);
    	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&map[i][j]),id[i][j]=++cnt;
    	s=Lux(p,1,1),t=Lux(0,n,n);
    	printf("%d
    ",spfa());
    	return 0;
    }
    



  • 相关阅读:
    NXOpen测量柱面两条边的最近距离
    NXOpen打开当前部件所在目录
    NXOpen 一键移除参数
    NXOpen 特征、体、线、圆弧、点通过迭代器遍历
    NXOpen批量创建部件
    NXOpen 创建圆柱面中心线
    NXOpen创建基准座标
    NXOpen 通过迭代器获取工作部件的体、面、边、点
    NXOpen 通过部件迭代器获取已加载部件的全路径
    NXOpen 批量导出STP、IGS、DWG、DXF、PDF(五合一)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4297957.html
Copyright © 2011-2022 走看看