[bzoj4992][Usaco2017 Feb][最短路]Why Did the Cow Cross the Road

20 篇文章 0 订阅
15 篇文章 0 订阅

Description

有一幅n*n的方格图,n <=100,每个点上有一个值。 \从(1,1)出发,走到(n,n),只能走上下左右。
每走一步花费t,每走三步需要花费走完三步后到达格子的值。 求最小花费的值。

Sample Input

4 2

30 92 36 10

38 85 60 16

41 13 5 68

20 97 13 80

Sample Output

31

题解

设d[x][y][0]表示到这格刚好需要拿权值的最小值
d[x][y][1],d[x][y][2]表示到这格多走了1步,2步的最小值(不需要取权值)
跑spfa即可

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[4]={0,-1,0,1};
const int dy[4]={-1,0,1,0};
int d[110][110][3];
int mp[110][110],n,T;
bool v[110][110];
bool chk(int x,int y)
{
    if(x<1 || x>n || y<1 || y>n)return false;
    return true;
}
struct pt
{
    int x,y;
}list[110000];int head,tail;
int main()
{
    scanf("%d%d",&n,&T);
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&mp[i][j]);
    memset(d,63,sizeof(d));d[1][1][0]=0;
    memset(v,false,sizeof(v));v[1][1]=true;
    list[1].x=1;list[1].y=1;;head=1;tail=2;
    while(head!=tail)
    {
        pt tmp=list[head];      
        for(int i=0;i<=3;i++)
            if(chk(tmp.x+dx[i],tmp.y+dy[i]))
            {
                int x=tmp.x+dx[i],y=tmp.y+dy[i];
                if(d[x][y][1]>d[tmp.x][tmp.y][0]+T)
                {
                    d[x][y][1]=d[tmp.x][tmp.y][0]+T;
                    if(!v[x][y])
                    {
                        v[x][y]=true;
                        list[tail].x=x;;list[tail].y=y;tail++;
                        if(tail==n*n+1)tail=1;
                    }
                }
                if(d[x][y][2]>d[tmp.x][tmp.y][1]+T)
                {
                    d[x][y][2]=d[tmp.x][tmp.y][1]+T;
                    if(!v[x][y])
                    {
                        v[x][y]=true;
                        list[tail].x=x;;list[tail].y=y;tail++;
                        if(tail==n*n+1)tail=1;
                    }
                }
                if(d[x][y][0]>d[tmp.x][tmp.y][2]+T+mp[x][y])
                {
                    d[x][y][0]=d[tmp.x][tmp.y][2]+T+mp[x][y];
                    if(!v[x][y])
                    {
                        v[x][y]=true;
                        list[tail].x=x;;list[tail].y=y;tail++;
                        if(tail==n*n+1)tail=1;
                    }
                }
            }
        head++;if(head==n*n+1)head=1;
        v[tmp.x][tmp.y]=false;
    }
    printf("%d\n",min(d[n][n][0],min(d[n][n][1],d[n][n][2])));
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值