4992: [Usaco2017 Feb]Why Did the Cow Cross the Road
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 190 Solved: 108
[ Submit][ Status][ Discuss]
Description
有一幅n*n的方格图,n <=100,每个点上有一个值。
\从(1,1)出发,走到(n,n),只能走上下左右。
每走一步花费t,每走三步需要花费走完三步后到达格子的值。
求最小花费的值。
Input
Output
Sample Input
4 2
30 92 36 10
38 85 60 16
41 13 5 68
20 97 13 80
30 92 36 10
38 85 60 16
41 13 5 68
20 97 13 80
Sample Output
31
我们把每一个格子当三个格子来看,来放 步数%3 ,f[x][y][s]可以更新f[x+dx[i]][y+dy[i]][(s+1)%3] , (s==0,1的时候f[x+dx[i]][y+dy[i]][(s+1)%3] =f[x][y][s]+t;s==2的时候f[x+dx[i]][y+dy[i]][(s+1)%3] =f[x][y][s]+t+v[x+dx[i]][y+dy[i]];)
我们把更新掉的状态放到队列里,直到队列为空就结束。
#include<cstdio>
#include<iostream>
#include<queue>
#define ll long long
#define INF (ll)1e16
#define N 105
using namespace std;
int v[N][N],n,t,cnt;
ll f[N][N][3];
queue<int>Q;
struct he{
int x,y,s;
}c[N*N*5];
const int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
int main(){
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&v[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=2;k++) f[i][j][k]=INF;
f[1][1][0]=0;
cnt++;
c[cnt].x=1;c[cnt].y=1;c[cnt].s=0;
Q.push(cnt);
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=0;i<4;i++){
int x1=c[u].x+dx[i],y1=c[u].y+dy[i],s1=(c[u].s+1)%3;
if(1<=x1&&x1<=n&&1<=y1&&y1<=n){
int tmp=0;
if(s1==0) tmp=1;
if(f[c[u].x][c[u].y][c[u].s]+t+tmp*v[x1][y1]<f[x1][y1][s1]){
f[x1][y1][s1]=f[c[u].x][c[u].y][c[u].s]+t+tmp*v[x1][y1];
cnt++;
c[cnt].x=x1;c[cnt].y=y1;c[cnt].s=s1;
Q.push(cnt);
}
}
}
}
printf("%lld",min(f[n][n][0],min(f[n][n][1],f[n][n][2])));
}