一道有点套路化的网格图上DPQwQ
我们用fmin[i][j][0]表示线头在(i,j)这个点的时候,线的方向朝__下__,我们能取到的最小的拐弯次数、用fmin[i][j][1]表示线头在(i,j)这个点的时候,显得方向朝__右__,能够取到的最小的拐弯次数
同理,我们用fmax[i][j][0]与fmax[i][j][1]表示线头在(i,j)位置是线朝下和朝右能够取到的最大的拐弯次数。
接下来,对于有障碍的点,我们直接不处理
显然,答案分别为max(fmax[n][m][0],fmax[n][m][1])与min(fmin[n][m][0],fmin[n][m][1])
接下来,我们就可以写出状态转移方程辣
fmin[i][j][0]=min(fmin[i−1][j][0],fmin[i−1][j][1]+1)
fmin[i][j][1]=min(fmin[i][j−1][1],fmin[i][j−1][0]+1)
fmax[i][j][0]=max(fmax[i−1][j][0],fmax[i−1][j][1]+1)
fmax[i][j][1]=max(fmax[i][j−1][1],fmax[i][j−1][0]+1)
注意初始化,fmin初始化为inf,fmax初始化为-1,注意边界~~
上代码QwQ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
#include<bits/stdc++.h>
#define INF 1000000000 #define ll long long
int Inp(){ char c = getchar(); int Neg = 1; while(c < '0' || c > '9'){ if(c == '-') Neg = -1; c = getchar(); } int Sum = 0; while(c >= '0' && c <= '9'){ Sum = ((Sum << 3) + (Sum << 1)) + c - '0'; c = getchar(); } return Neg * Sum; }
int f_max[1010][1010][3]; int f_min[1010][1010][3]; char s[1010][1010];
int main(){ int n = Inp(); int m = Inp(); for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1); for(int i = 0; i <= n; i++) for(int j = 0; j <= m; j++){ f_max[i][j][0] = f_max[i][j][1] = -1; f_min[i][j][0] = f_min[i][j][1] = INF; } for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){ if(s[i][j] == '#') continue; if(i == 1 && j == 1){ f_max[1][1][0] = f_max[1][1][1] = 0; f_min[1][1][0] = f_min[1][1][1] = 0; continue; } f_min[i][j][0] = std::min(f_min[i - 1][j][0], f_min[i - 1][j][1] + 1); f_min[i][j][1] = std::min(f_min[i][j - 1][1], f_min[i][j - 1][0] + 1); f_max[i][j][0] = std::max(f_max[i - 1][j][0], f_max[i - 1][j][1] + 1); f_max[i][j][1] = std::max(f_max[i][j - 1][1], f_max[i][j - 1][0] + 1); } if(std::min(f_min[n][m][0], f_min[n][m][1]) == INF){ printf("-1"); return 0; } printf("%d %d", std::max(f_max[n][m][0], f_max[n][m][1]) - 1, std::min(f_min[n][m][0], f_min[n][m][1])); }
|