【洛谷P3659】[USACO17FEB]Why Did the Cow Cross the Road I G

题目描述:

奶牛们为什么要穿马路?一个原因只是因为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;
}
原文地址:https://www.cnblogs.com/huihao/p/7757912.html