走迷宫2

走迷宫2

1000ms
65535KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                    
  • 走迷宫是很有趣的一种游戏,能够锻炼人的记忆力和思维.现在,HK被困在一个迷宫里面了,请你帮助他计算一下有多少种不同的走法,能够让他走出迷宫.这个迷宫很奇怪,HK只能够沿着向上或者向右的方向走,不能回头.

    迷宫使用一个N*M的矩阵来描述,矩阵中用'.'代表空格可以通行,用'*'代表障碍物,用'S'代表出发点,用'T'代表出口.例如下面的一个矩阵就描述了一个8*8的迷宫


    .....T..
    ..*****.
    ......*.
    *.***.*.
    ......*.
    .****.*.
    S..*....
    ........

    Input

    每个输入文件只包含一组输入数据.
    每组数据第一行是两个正整数N和M(N,M<=100).
    接着是一个N*M的矩阵.

    Output

    输出HK能够选用的不同方法数(由于结果可能很大,输出模1908的余数即可).

    Sample Input

    8 8
    .....T..
    ..*****.
    ......*.
    *.***.*.
    ......*.
    .****.*.
    S..*....
    ........

    Sample Output

    1
    

    Source

    Author

    HK@Sphinx

    Tags ( Click to see )

    作为小白,刚刚看到题很兴奋的以为是DFS,还以为终于可以自己写一次DFS,然后交了一次DFS,结果TLE,我家大神看了下默默地说了句应该是DP,然后就把我这只小白晾一边让我自己去想。嘛。扳手指扳了好久才磨出来,虽然是很简单的DP,但是自己写出来心情还是很愉悦~

    题目限定只能向上、向右走,不能回头,所以新的状态只能由它左边或者下面的状态转移而来,假设新状态为dp[i][j],那么转移方程就为dp[i][j] = dp[i][j+1] + dp[i-1][j]。另外:①因为新状态是通过枚举横纵坐标,都是从起点开始的,所以初始化起点对应的dp值为1之后,要将起点标记为不能更新;②要能够走出迷宫,在满足题意的要求下,可以将整张图抽象为一个矩形,起点应该在矩形左下角,终点在矩形右上角,终点的值只能沿着矩形的边转移而来,所以找到终点可以直接break。

    此处附上TLE的DFS代码,一次纪念本小白第一次写的DFS:

    #include"cstdio"
    #include"cstring"
    #include"iostream"
    #include"algorithm"
    
    using namespace std;
    
    char maze[105][105];
    
    int ans;
    int N,M;
    bool vis[105][105];
    
    bool is_block(int x,int y)
    {
        if(x<0 || x>=N || y<0 || y>=M)
        {
            return true;
        }
        if(maze[x][y] == '*')
        {
            return true;
        }
        return false;
    }
    
    void dfs(int x,int y)
    {
        if(maze[x][y] == 'T')
        {
            ans ++;
            ans %= 1908;
            return;
        }
        if(!vis[x-1][y] && !is_block(x-1,y))
        {
            vis[x-1][y] = true;
            dfs(x-1,y);
            vis[x-1][y] = false;
        }
        if(!vis[x][y+1] && !is_block(x,y+1))
        {
            vis[x][y+1] = true;
            dfs(x,y+1);
            vis[x][y+1] = false;
        }
    }
    
    int main()
    {
        while(~scanf("%d%d",&N,&M))
        {
            for(int i = 0;i < N;i++)
            {
                scanf("%s",maze[i]);
            }
            
            ans = 0;
            memset(vis,false,sizeof(vis));
            for(int i = 0;i < N;i++)
            {
                for(int j = 0;j < M;j++)
                {
                    if(maze[i][j] == 'S')
                    {
                        dfs(i,j);
                        break;
                    }
                }
            }
            ans %= 1908;
            printf("%d\n",ans);
        }
        return 0;
    }

    AC代码:

    #include"cstdio"
    #include"cstring"
    #include"iostream"
    #include"algorithm"
    
    using namespace std;
    
    char maze[105][105];
    int dp[105][105];
    int N,M;
    
    bool is_block(int x,int y)
    {
        if(x<1 || x>N || y<1 || y>M)
        {
            return true;
        }
        if(maze[x][y] == '*')
        {
            return true;
        }
        return false;
    }
    
    int main()
    {
        while(~scanf("%d%d",&N,&M))
        {
            int x,y;
            for(int i = 1;i <= N;i++)
            {
                for(int j = 1;j <= M;j++)
                {
                    cin >> maze[i][j];
                    if(maze[i][j] == 'S')
                    {
                        x = i;
                        y = j;
                    }
                }
            }
            memset(dp,0,sizeof(dp));
            dp[x][y] = 1;
            maze[x][y] = '*'; //标记为不能更新
            int ans;
            for(int i = x;i > 0;i--)
            {
                for(int j = y;j <= M;j++)
                {
                    if(!is_block(i,j))
                    {
                        dp[i][j] = dp[i][j-1] + dp[i+1][j];
                    }
                    if(maze[i][j] == 'T')
                    {
                        ans = dp[i][j]%1908;
                        break;
                    }
                }
            }
            printf("%d\n",ans%1908);
        }
        return 0;
    }
    



    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值