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;
}