题目描述:
奶牛们为什么要穿马路?一个原因只是因为FJ的牧场的路实在是太多了,使得奶牛们每天不得不穿梭在许许多多的马路中央
FJ的牧场可以看作是一块 N*N 的田地(3<=N<=100),N-1 条南北向的道路和 N-1 条东西向的道路贯穿整个牧场,同时是每块田野的分界线。牧场的最外面是一圈高大的栅栏以防止奶牛离开牧场。Bessie只要穿过分离两块田野的道路,就可以从任何田野移动到与其相邻的田野里去(北,东,南或西)。当然,Bessie穿过每一条马路都是需要 T 时间的。(0<=T<=1,000,000)
有一天,FJ邀请Bessie来他家下棋,Bessie从牧场的西北角出发,FJ的家在牧场的东南角。因为Bessie在中途可能会饿,所以她每走过三块田野就要停下来,享用她所在田野上的新鲜的牧草(不包括Bessie的出发点,但是可能会包括终点FJ的家),牧场上有些田野的牧草长得比其他地方茂盛,所以Bessie对应的停留时间也会变长。
请帮帮Bessie计算出她走到FJ家的最短时间。
输入输出格式
输入格式:
第一行两个数N,T。
接下来 N 行,每行 N 个数表示每块田野Bessie需要停留的时间(每块最多不超过100,000),第一行的第一块田野是牧场的西北角。
输出格式:
一行一个整数表示Bessie走到FJ家的最短时间。
说明:
对于样例,Bessie先向东走过了三块田野(在“10”停留),再向南走两步,又向西走了一步(在“5”停留),最后向南走一步,再向东走一步到达FJ的家(不用停留),总共时间是15(停留时间)+16(穿马路时间)=31。
分析
转载Slager_Z大佬的题解。
代码
来自Slager_Z大佬。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> using namespace std; int n,v[110][110]; long long dis[110][110],t; bool vis[110][110]; struct node { int x,y; }; int dx[]={0,0,3,-3,1,1,2,2,-1,-1,-2,-2,0,0,1,-1}; int dy[]={3,-3,0,0,2,-2,1,-1,2,-2,1,-1,1,-1,0,0}; void spfa(int x,int y) { queue<node>q; q.push((node){x,y}); memset(dis,0x7f,sizeof(dis)); dis[x][y]=0; vis[x][y]=1; do { node u=q.front();q.pop(); vis[u.x][u.y]=0; for(int i=0;i<16;i++) { int tx=u.x+dx[i],ty=u.y+dy[i]; if(tx>=1&&tx<=n&&ty>=1&&ty<=n) { if(dis[tx][ty]>dis[u.x][u.y]+v[tx][ty]+t*3) { dis[tx][ty]=dis[u.x][u.y]+v[tx][ty]+t*3; if(!vis[tx][ty]) { vis[tx][ty]=1;q.push((node){tx,ty}); } } } } }while(q.size()!=0); } int main() { ios::sync_with_stdio(false); cin>>n>>t; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>v[i][j]; spfa(1,1); long long ans; ans=dis[n][n];//参照题解:牛不可能直接到达,所以得枚举终点3步之内的所有点的值+位移的时间; ans=min(ans,dis[n][n-1]+t); ans=min(ans,dis[n-1][n]+t); ans=min(ans,dis[n][n-2]+t*2); ans=min(ans,dis[n-2][n]+t*2); ans=min(ans,dis[n-1][n-1]+t*2); printf("%lld",ans); return 0; }