UVa116 題敘 http://domen111.github.io/UVa-Easy-Viewer/?116
想法 實作dfs很簡單,但是需要能回朔解 這邊想到用陣列去記錄每個點要前往的x座標,而y座標固定是+1,故不紀錄 在更新Min_dis要特別注意維護x較小的要在前 並且當Min_dis已經為最小值時DFS可以直接return減少遞迴時間
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #include <bits/stdc++.h> #define LL long long #define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); #define pii pair<int,int> using namespace std ;int m,n,arr[15 ][105 ],Min_dis[15 ][105 ],to[15 ][105 ];int dir[3 ]={-1 ,0 ,1 };int next (int x) { if (x<0 ) return m-1 ; else if (x>=m) return 0 ; else return x; } int dfs (int x,int y) { if (y+1 ==n){ return Min_dis[x][y]=arr[x][y]; } if (Min_dis[x][y]!=2147483647 ) return Min_dis[x][y]; for (int i=0 ; i<3 ; i++){ int nx=next(x+dir[i]); int ny=y+1 ; int dis=dfs(nx,ny); if (dis+arr[x][y]<Min_dis[x][y]){ Min_dis[x][y]=dis+arr[x][y]; to[x][y]=nx; } else if (dis+arr[x][y]==Min_dis[x][y] && to[x][y]>nx){ to[x][y]=nx; } } return Min_dis[x][y]; } int main () { IOS while (cin >>m>>n){ for (int i=0 ; i<m ; i++){ for (int j=0 ; j<n ; j++){ Min_dis[i][j]=2147483647 ; cin >>arr[i][j]; } } int ans=0 ,tot=2147483647 ; for (int i=0 ; i<m ; i++){ int res=dfs(i,0 ); if (res<tot){ tot=res; ans=i; } } bool out=false ; for (int start=ans,j=0 ; j<n ; j++){ if (out) cout <<" " ; else out=true ; cout <<start+1 ; start=to[start][j]; } cout <<'\n' ; cout <<tot<<"\n" ; } return 0 ; }
複雜度分析 每次狀態轉移複雜度為 $O(1)$,總共有$n\times m$ 種狀態 總複雜度 $O(nm)$