P2802 回家(洛谷)
阿新 • • 發佈:2020-09-12
題目傳送門:
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; //初始的血量為6int 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; }