UVA1600 Dfs回溯完全遍历+记忆化搜索(用最小距离剪枝)+细节处理 (值得复习)(水)

0)
 题意和样例很清晰,不解释了。
1)
有三处需要注意的,处理该类问题的细节:
Error ①:因为是Dfs递归处理,所以不能直接return moves,否则又一层一层退回来,并没有记录moves值。
Error ②:注意对于走过的点,应该做标记,否则可能出现这样的情况,假如dir方向数组前两个方向依次是向下和向右,那么A点往下走到B点,B点下面没有了,往上走到A点,A点又走到B点。于是递归不结束,输出异常值或者程序崩溃;其次,应该在进入Dfs()语句的前后依次进行标记和消除标记,因为用Dfs递归走完每一种情况的路径,那么该点走过仅仅是对于这一条递归路径而言,对于这一层或者之前的其他的递归路径这一个点还是未走过的。
Error ③:虽然起点和终点,分别对应地图左上角和右下角两个点,但是中间路径未必只是向右或向下;每个点有四个方向可以选择,注意x、y依次对应地图的上下移动、左右移动。

2)

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;
int mat[30][30];
int bj[30][30];
int dis[30][30];
//int dir[2][2]={{1,0},{0,1}};              // Error ③
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int m,n;//row col
int max_continuous;
int sum;
void Dfs(int cur_x,int cur_y,int moves,int cur_continuous){
    //cout<<"cur: "<<cur_x<<" "<<cur_y<<" moves: "<<moves<<"  cur_continuous: "<<cur_continuous<<endl;
    //bj[cur_x][cur_y]=1;                    // Error ②
    if(cur_x==m&&cur_y==n){
        //cout<<"endd_moves:"<<moves<<endl;  // Error ①
        //return moves;
        if(moves<sum||sum==-1)
            sum=moves;
        return ;
    }
    int next_x;
    int next_y;
    int next_continuous;
    for(int k=0;k<=3;k++){
        next_x=cur_x+dir[k][0];
        next_y=cur_y+dir[k][1];
        if(next_x>m||next_x<1||next_y>n||next_y<1){
            continue;
        }
        if(bj[next_x][next_y]==1){
            continue;
        }
        if(mat[next_x][next_y]==1){
            next_continuous=cur_continuous+1;
            if(next_continuous<=max_continuous){
                //cout<<"question:"<<next_continuous<<" "<<k<<endl;
                if(moves+1<=dis[next_x][next_y]||dis[next_x][next_y]==-1){
                    dis[next_x][next_y]=moves+1;
                    bj[next_x][next_y]=1;
                    Dfs(next_x,next_y,moves+1,next_continuous);
                    bj[next_x][next_y]=0;
                }
            }
        }
        else{
            next_continuous=0;
            if(next_continuous<=max_continuous){
                if(moves+1<=dis[next_x][next_y]||dis[next_x][next_y]==-1){
                    dis[next_x][next_y]=moves+1;
                    bj[next_x][next_y]=1; // Error ②
                    Dfs(next_x,next_y,moves+1,next_continuous);
                    bj[next_x][next_y]=0; // Error ②
                }
            }
        }
    }
}
int main(){
    int kase;
    cin>>kase;

    while(kase--){
        sum=-1;
        memset(dis,-1,sizeof(dis));
        dis[0][0]=0;
        memset(mat,0,sizeof(mat));
        memset(bj,0,sizeof(bj));
        cin>>m>>n>>max_continuous;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&mat[i][j]);
            }
        }
        Dfs(1,1,0,0);//DFS递归的形式,完全遍历每一种情况,用dis数组存储到达每个点的最小距离,用于剪枝以达到记忆化搜索的目的。
        cout<<sum<<endl;

    }

    return 0;
}

3)

Description

Download as PDF

A robot has to patrol around a rectangular area which is in a form of mxn grid (m rows andn columns). The rows are labeled from 1 tom. The columns are labeled from 1 to n. A cell(i, j) denotes the cell in rowi and column j in the grid. At each step, the robot can only move from one cell to an adjacent cell, i.e. from(x,y) to (x + 1,y), (x, y + 1), (x - 1, y) or(x, y - 1). Some of the cells in the grid contain obstacles. In order to move to a cell containing obstacle, the robot has to switch to turbo mode. Therefore, the robot cannot move continuously to more thank cells containing obstacles.

Your task is to write a program to find the shortest path (with the minimum number of cells) from cell (1, 1) to cell(m,n). It is assumed that both these cells do not contain obstacles.

Input 

The input consists of several data sets. The first line of the input file contains the number of data sets which is a positive integer and is not bigger than 20. The following lines describe the data sets.

For each data set, the first line contains two positive integer numbers m and n separated by space (1$ \le$m,n$ \le$20). The second line contains an integer numberk(0$ \le$k$ \le$20). The ith line of the nextm lines containsn integeraij separated by space(i = 1, 2,...,m;j = 1, 2,..., n). The value of aij is1 if there is an obstacle on the cell(i, j), and is 0 otherwise.

Output 

For each data set, if there exists a way for the robot to reach the cell (m, n), write in one line the integer number s, which is the number of moves the robot has to make; -1 otherwise.

Sample Input 

3 
2 5 
0 
0 1 0 0 0 
0 0 0 1 0 
4 6 
1 
0 1 1 0 0 0
0 0 1 0 1 1
0 1 1 1 1 0
0 1 1 1 0 0
2 2 
0 
0 1 
1 0

Sample Output 

7 
10 
-1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值