Gym 101617D
题意:
有一个nXn的图,由.和#组成,现在从1,1出发,每次跳最多k个格子,落点不能是#,问到(n,n)最少需要几步,如果无法到达则输出-1.注意只能向右和下走。
思路:
此题可以从dp方式来思考,当走到当前一步时,最重要的是判断从哪里开始,从上或者左,不妨开两个数组a和b分别记录行和列的信息: a[j] 保存当前j列中.所在的位置
b[i] 表示能够到达当前i行中.所在的位置
- 需要更新最优的位置。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 2005;
const int inf = 0x3f3f3f3f;
int n,k;
char s[maxn][maxn];
int dp[maxn][maxn],a[maxn],b[maxn];
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&k);
for(int i = 1;i <= n; i++)
scanf("%s",s[i]+1);
memset(dp,inf,sizeof(dp));
dp[1][1] = 0;
for(int i = 1;i <= n; i++) {
for(int j = 1;j <= n; j++) {
if(i == 1 && j == 1) continue;
if(s[i][j] == '#') continue;
for(;a[j] < i; a[j]++)
if((i-a[j]) <= k && s[a[j]][j] == '.') break;
dp[i][j] = min(dp[i][j],dp[a[j]][j]+1);
for(;b[i] < j; b[i]++)
if((j-b[i]) <= k && s[i][b[i]] == '.') break;
dp[i][j] = min(dp[i][j],dp[i][b[i]]+1);
if(dp[i][j] <= dp[a[j]][j]) a[j] = i;
if(dp[i][j] <= dp[i][b[i]]) b[i] = j;
}
}
printf("%d\n",dp[n][n] == inf ? -1:dp[n][n]);
return 0;
}