1. 程式人生 > 實用技巧 >P2802 回家(洛谷)

P2802 回家(洛谷)

題目傳送門:

https://www.luogu.com.cn/problem/P2802

題解思路:

AC程式碼:

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int n,m;
int a[10][10];      //儲存地圖
int color[10][10]={0};      //標記用,防止出現重複走動而死迴圈的情況
//注意  雖然有標記但是這裡是搜尋路徑問題  所以在每層的dfs結束時都需要進行回溯
int xue=6;              //初始的血量為6
int path=120; //最短路長 // int step=0; int dx[4]={-1,0,1,0}; int dy[4]={0,-1,0,1}; void dfs(int i,int j,int xue,int step){ //先判斷是否死亡 if(xue<=0) return; //直接退出 if(step>=n*m) return;//剪枝操作 if(step>path) return;//剪枝操作 if(a[i][j]==3){ if(path>step){//剪枝操作
path=step; //更新最小路徑 } return; } if(a[i][j]==4) xue=6; //血量加滿 for(int k=0;k<4;k++){ int tx=i+dx[k]; int ty=j+dy[k]; if(a[tx][ty]!=0){ dfs(tx,ty,xue-1,step+1); } } } int main(){ cin>>n>>m;
for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>a[i][j]; } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i][j]==2){ //出發地 dfs(i,j,6,0); break; } } } if(path==120){ //表示沒回家 cout<<"-1"; } else{ cout<<path; } return 0; }

使用回溯時的程式碼(與上面進行對比,只通過了8個樣例):

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int n,m;
int a[10][10];      //儲存地圖
int color[10][10]={0};      //標記用,防止出現重複走動而死迴圈的情況
//注意  雖然有標記但是這裡是搜尋路徑問題  所以在每層的dfs結束時都需要進行回溯
int xue=6;              //初始的血量為6
int path=120;        //最短路長
int step=0;

int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
void dfs(int i,int j){
    if(color[i][j]==1)  return;     //表示之前走過
    //先判斷是否死亡
    if(xue<=0)  return;     //直接退出

    if(a[i][j]==3){             //剪枝操作
        if(path>step){
            path=step;      //更新最小路徑
        }
        return;
    }
    color[i][j]=1;      //標記
    if(a[i][j]==4)  xue=6;      //血量加滿

    for(int k=0;k<4;k++){
        int tx=i+dx[k];
        int ty=j+dy[k];

        if(a[tx][ty]!=0){
            step++;     //  只有移動時才有步數加1
            xue--;      //順便血量先減去1
            dfs(tx,ty);
            step--;
            xue++;      //xue和step是捆綁的
        }
    }

    color[i][j]=0;
    //回溯的時候標記取消 血量回加
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>a[i][j];
        }
    }

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i][j]==2){     //出發地
                dfs(i,j);
            }
        }
    }

    if(path==120){      //表示沒回家
        cout<<"-1";
    }
    else{
        cout<<path;
    }
    return 0;
}