题解:P1359 租用游艇
思路
橙题的难度不大,因此本题解主要梳理不同思路。
-
由于本题要求的是最短路,那么可以从最短路的角度分析:
-
直接推动态规划的转移方程式。
-
逆向思维。从 \(n\) 倒推,用 \(f_i\) 存储 \(i\) 到 \(n\) 的距离。边界条件为 \(f_n=0\)。那么显然从 \(n-1\) 遍历到 \(1\),每次的路径都是 \(i \rightarrow j (i<j<n) \rightarrow n\)。由于我们遍历的顺序,我们已知 \(j \rightarrow n\) 这一段的路程。因此转移方程式为:
\[f_i=min^{j=i+1}_{j<n}(r_{i,j} + f_j) \]然后做完了。
#include<bits/stdc++.h> #define ll long long #define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) using namespace std; const int N=205; const int inf=1e9; int n,r[N][N],f[N]; signed main(){ ios;cin>>n; for(int i=1;i<=n;i++){ f[i]=inf; // 设为无穷大 } f[n]=0; for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++){ cin>>r[i][j]; r[j][i]=r[i][j]; } } for(int i=n-1;i>=1;i--){ for(int j=i+1;j<=n;j++){ f[i]=min(f[i],f[j]+r[i][j]); } } cout<<f[1]<<'\n'; return 0; } -
考虑从 Floyd 中优化掉一维。用 \(f_i\) 存储 \(1\) 到 \(i\) 的距离。边界条件为 \(f_1=0\)。每次固定 \(i\) 后遍历 \(1\) 到 \(i-1\) 间的点进行松弛操作,也就是:
\[f_i=min^{j=1}_{j<i}(f_j + r_{j,i}) \]其中,由于道路双向可达,\(r_{i,j} = r_{j,i}\)。然后做完了。
#include<bits/stdc++.h> #define ll long long #define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) using namespace std; const int N=205; const int inf=1e9; int n,r[205][205],f[205]; signed main(){ ios;cin>>n; for(int i=1;i<=n;i++){ f[i]=inf; // 设为无穷大 } f[1]=0; for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++){ cin>>r[i][j]; r[j][i]=r[i][j]; } } for(int i=1;i<=n;i++){ for(int j=1;j<i;j++){ f[i]=min(f[i],f[j]+r[i][j]); } } cout<<f[n]<<'\n'; return 0; }
-
写了这么多,这题的多种思路梳理也就结束了。
感谢阅读!完结撒花花!
本文来自博客园,作者:Circle_Table,转载请注明原文链接:https://www.cnblogs.com/Circle-Table/articles/19501511

浙公网安备 33010602011771号