【bzoj4992: [Usaco2017 Feb]Why Did the Cow Cross the Road】动规

4992: [Usaco2017 Feb]Why Did the Cow Cross the Road

Time Limit: 10 Sec   Memory Limit: 256 MB
Submit: 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

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


猜你喜欢

转载自blog.csdn.net/bingoo0o0o/article/details/78740199