思路:
dp+记录路径
状态:dp[i][j]表示到(i,j)这个位置为止的最少花费
初始状态:dp[1][i]=a[1][i](1<=i<=m)
状态转移:dp[i][j]=a[i][j]+max(dp[i-1][j],dp[i][j-1],dp[i][j+1])(注意扫的方向不同)
数组记录上一次的坐标,最后递归输出
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=505; const int INF=0x3f3f3f3f; int a[N][N]; int dp[N][N]; pair<int,int> pre[N][N]; void dfs(int x,int y){ if(x==-1||y==-1)return ; dfs(pre[x][y].first,pre[x][y].second); cout<<y<<‘ ‘; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,m; mem(a,INF); mem(dp,INF); 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++)pre[i][j].first=-1,pre[i][j].second=-1; for(int i=1;i<=m;i++)dp[1][i]=a[1][i]; for(int i=2;i<=n;i++){ for(int j=1;j<=m;j++){ if(dp[i][j]>a[i][j]+dp[i-1][j]){ dp[i][j]=a[i][j]+dp[i-1][j]; pre[i][j].first=i-1; pre[i][j].second=j; } if(dp[i][j]>a[i][j]+dp[i][j-1]){ dp[i][j]=a[i][j]+dp[i][j-1]; pre[i][j].first=i; pre[i][j].second=j-1; } } for(int j=m;j>=1;j--){ if(dp[i][j]>a[i][j]+dp[i-1][j]){ dp[i][j]=a[i][j]+dp[i-1][j]; pre[i][j].first=i-1; pre[i][j].second=j; } if(dp[i][j]>a[i][j]+dp[i][j+1]){ dp[i][j]=a[i][j]+dp[i][j+1]; pre[i][j].first=i; pre[i][j].second=j+1; } } } int ans=INF,id=0; for(int i=1;i<=m;i++){ if(dp[n][i]<ans){ ans=dp[n][i]; id=i; } } int x=n,y=id; dfs(x,y); cout<<endl; return 0; }