Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2)

传送门

D. Explorer Space

题意:给一个矩阵,告诉你每点相邻边的花费,求每个点k步后回到原点的最短距离。

题解:首先当k为奇数时,一定回不到原点直接输出-1。当k为偶数时,可以理解为该点用了k/2步走了出去,又用k/2步走了回来,易知要距离最短所以出去和回来的路径一定一样,所以题目就转化为了,走k/2步最少能用多少花费,直接记忆化即可。

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
const ll N=507;
const ll inf=1e18;
ll n,m,k,a[N][N],b[N][N],d[N][N][4],f[N][N][17];
ll dx[]={0,0,-1,1};
ll dy[]={1,-1,0,0};
ll dfs(ll x,ll y,ll k){
	if(k==0){
		return 0;
	}
	ll mi=inf;
	if(f[x][y][k]!=-1){
		return f[x][y][k];
	}
	for(int i=0;i<4;i++){
		ll tx=x+dx[i];
		ll ty=y+dy[i];
		if(1<=tx&&tx<=n&&1<=ty&&ty<=m){
			mi=min(mi,dfs(tx,ty,k-1)+d[x][y][i]);
		}
	}
	return f[x][y][k]=mi;
}
ll gao(ll x,ll y){
	if(k%2==1){
		return -1;
	}
	else{
		return dfs(x,y,k/2)*2;
	}
}
int main(){
	memset(f,-1,sizeof(f));
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=n;i++){
		for(int j=1;j<m;j++){
			scanf("%lld",&a[i][j]);
			d[i][j][0]=a[i][j];
			d[i][j+1][1]=a[i][j];
		}
	}
	for(int i=1;i<n;i++){
		for(int j=1;j<=m;j++){
			scanf("%lld",&b[i][j]);
			d[i][j][3]=b[i][j];
			d[i+1][j][2]=b[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			printf("%lld ",gao(i,j));
		}puts("");
	}
}
原文地址:https://www.cnblogs.com/whitelily/p/14696086.html