Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2) D. Explorer Space (记忆化搜索)

-
题意:有一个\(n\)x\(m\)的矩阵,相邻点之间都存在边权,每次可以移动到相邻点,问你每个点移动\(k\)次后并回到该点的最短边权和.
-
题解:如果\(k\)是奇数的话,一定不能走回到自己,因为线段来回来走两次或走一个矩阵,他们的边长和都是偶数.\(dp[i][j][k]\)表示点\((i,j)\)走\(k\)次后回到自己的最短边权和,很明显这个状态我们确定后就不会在修改他了,那么可以直接记忆化搜索.
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n,m,k; int row[505][505],col[505][505]; int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; ll dp[505][505][25]; ll dfs(int x,int y,int cnt){ if(cnt==0) return 0; if(dp[x][y][cnt]) return dp[x][y][cnt]; ll res=1e18; if(x!=1) res=min(res,dfs(x-1,y,cnt-1)+col[x-1][y]); if(x!=n) res=min(res,dfs(x+1,y,cnt-1)+col[x][y]); if(y!=1) res=min(res,dfs(x,y-1,cnt-1)+row[x][y-1]); if(y!=m) res=min(res,dfs(x,y+1,cnt-1)+row[x][y]); return dp[x][y][cnt]=res; } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>n>>m>>k; rep(i,1,n){ rep(j,1,m-1){ cin>>row[i][j]; } } rep(i,1,n-1){ rep(j,1,m){ cin>>col[i][j]; } } if(k&1){ rep(i,1,n){ rep(j,1,m){ cout<<-1<<' '; } cout<<'\n'; } } else{ rep(i,1,n){ rep(j,1,m){ cout<<dfs(i,j,k/2)*2<<' '; } cout<<'\n'; } } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮

浙公网安备 33010602011771号