牛客练习赛58 D.迷宫

牛客练习赛58 D.迷宫

题目链接

题目描述

有一个n∗m迷宫,迷宫中每个格子用0或1表示,0表示该格子可以通过,1表示该格子是个障碍物,牛妹站在格子(1,1),出口在格子(n,m),牛妹想要走出迷宫,但牛妹只会按以下策略走:

牛妹当前所在的格子称为当前格子

1.如果当前格子右边没有障碍物,牛妹就向右走,否则转到2。
2.如果当前格子下方没有障碍物,牛妹就向下走,否则转到3。
3.如果当前格子左边没有障碍物,牛妹就向左走,否则转到4。
4.如果当前格子上方没有障碍物,牛妹就向上走,否则转到5。
5.牛妹站在原地不动。

由于牛妹按这样的策略可能会无法走到出口,牛妹的好朋友牛牛决定在牛妹离开格子(1,1)前把迷宫中的一些非障碍格子变成障碍,帮助牛妹走出迷宫,但是牛牛比较懒,他想要最小化变成障碍的非障碍格子的数量。

输入描述:

第一行两个整数n,m表示迷宫的大小
接下来n行每行一个长度为m的01串表示迷宫的格局

输出描述:

输出一个整数表示牛牛最少需要转换成障碍格子的非障碍格子的数量,如果无法帮助牛妹走出迷宫,输出−1。

示例1

输入

4 4
0000
0110
0110
0000

输出

0

比赛时一直想不到好的做法,看了题解才发现是简单DP,牛妹不可能往左或往上走,那么就按以下策略DP即可:
1.向右走, d p [ i ] [ j + 1 ] = m i n ( d p [ i ] [ j + 1 ] , d p [ i ] [ j ] ) dp[i][j+1]=min(dp[i][j+1],dp[i][j]) dp[i][j+1]=min(dp[i][j+1],dp[i][j])
2.向下走,若 a [ i + 1 ] [ j ] = 1 , d p [ i + 1 ] [ j ] = m i n ( d p [ i + 1 ] [ j ] , d p [ i ] [ j ] ) ; 若 a [ i + 1 ] [ j ] = 0 , d p [ i + 1 ] [ j ] = m i n ( d p [ i + 1 ] [ j ] , d p [ i ] [ j ] + 1 ) a[i+1][j]=1,dp[i+1][j]=min(dp[i+1][j],dp[i][j]);若a[i+1][j]=0,dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1) a[i+1][j]=1,dp[i+1][j]=min(dp[i+1][j],dp[i][j]);a[i+1][j]=0,dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1)

AC代码如下:

#include
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e3+5;
int n,m,dp[N][N];
char s[N][N];

int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>s[i][j];
        }
    }
    fill(dp[0],dp[0]+N*N,inf);
    dp[0][0]=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(s[i][j]=='0'){
                if(j<m-1 && s[i][j+1]=='0')
                    dp[i][j+1]=min(dp[i][j+1],dp[i][j]);
                if(i<n && s[i+1][j]=='0'){
                    if(j==m-1 || s[i][j+1]=='1')
                        dp[i+1][j]=min(dp[i+1][j],dp[i][j]);
                    else dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1);
                }
            }
        }
    }
    if(dp[n-1][m-1]==inf) printf("-1\n");
    else printf("%d\n",dp[n-1][m-1]);
}

你可能感兴趣的:(动态规划,牛客)