«问题描述:
给定一个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。
设计一个算法,求出汽车从起点出发到达终点的一条所付费用最少的行驶路线。

«编程任务:
对于给定的交通网格,计算汽车从起点出发到达终点的一条所付费用最少的行驶路线。
«数据输入:
由文件trav.in提供输入数据。文件的第一行是N,K,A,B,C的值。第二行起是一
个N*N 的0-1 方阵,每行N 个值,至N+1 行结束。方阵的第i 行第j 列处的值为1 表示在
网格交叉点(i,j)处设置了一个油库,为0 时表示未设油库。各行相邻两个数以空格分隔。
«结果输出:
程序运行结束时,将最小费用输出到文件trav.out中。
输入文件示例 输出文件示例
trav.in
9 3 2 3 6
0 0 0 0 1 0 0 0 0
0 0 0 1 0 1 1 0 0
1 0 1 0 0 0 0 1 0
0 0 0 0 0 1 0 0 1
1 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0 1
1 0 0 1 0 0 0 1 0
0 1 0 0 0 0 0 0 0
trav.out
12


【分析】
分层图尼玛尼玛尼玛尼玛
c要加a尼玛尼玛尼玛尼玛尼玛尼玛尼玛尼玛
板鸡板鸡板鸡板鸡板鸡板鸡板鸡
都怪我没脑子没脑子没脑子没脑子

楼主已经气成了神经病↑


【代码】

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define ll long long
#define p(k,i,j) (k)*n*n+(i-1)*n+(j)
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=1500005;
int n,k,a,b,c,e,cnt,ans;
bool vis[mxn];
int head[mxn],mp[105][105],dis[mxn];
int dx[5]={0,-1,0,1,0},dy[5]={0,0,-1,0,1};
struct edge {int to,next,d;} f[mxn<<1];
inline void add(int u,int v,int d)
{
f[++cnt].to=v,f[cnt].next=head[u],f[cnt].d=d,head[u]=cnt;
}
inline void spfa()
{
int i,j;
queue <int> q;
memset(dis,0x3f,sizeof dis);
dis[p(k,1,1)]=0;
q.push(p(k,1,1));
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=f[i].next)
{
int v=f[i].to,d=f[i].d;
if(dis[v]>dis[u]+d)
{
dis[v]=dis[u]+d;
if(!vis[v]) vis[v]=1,q.push(v);
}
}
}
ans=1e9+7;
fo(i,0,k)
ans=min(ans,dis[p(i,n,n)]);
printf("%d\n",ans);
}
int main()
{
freopen("trav.in","r",stdin);
freopen("trav.out","w",stdout);
int i,j,x,y,u,v,yu;
scanf("%d%d%d%d%d",&n,&k,&a,&b,&c);
fo(i,1,n) fo(j,1,n) scanf("%d",&mp[i][j]);
fo(x,1,n) fo(y,1,n)
fo(yu,1,k)
{
u=p(yu,x,y);
fo(e,1,4)
if(x+dx[e]>=1 && x+dx[e]<=n && y+dy[e]>=1 && y+dy[e]<=n)
{
if(mp[x+dx[e]][y+dy[e]]) //如果到了油站
{
if(e<=2) add(u,p(k,x+dx[e],y+dy[e]),a+b);
else add(u,p(k,x+dx[e],y+dy[e]),a);
}
else
{
if(e<=2) add(u,p(yu-1,x+dx[e],y+dy[e]),b),add(u,p(k,x+dx[e],y+dy[e]),b+c+a);
else add(u,p(yu-1,x+dx[e],y+dy[e]),0),add(u,p(k,x+dx[e],y+dy[e]),c+a);
}
}
}
spfa();
return 0;
}
/*
2 1 2 2 2
0 0
0 0
*/