首页 > 代码库 > 【线性规划与网络流24题】汽车加油行驶问题 分层图
【线性规划与网络流24题】汽车加油行驶问题 分层图
汽车加油行驶问题
Time Limit: 1 Sec Memory Limit: 128 MBDescription
给定一个 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
Sample Output
Source
网络流24题
题意依然不加赘述,题解也不难说,就是比裸最短路多几种转移方式,我不说转移方程了,代码写得很漂亮。
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\n",spfa()); return 0; }
【线性规划与网络流24题】汽车加油行驶问题 分层图