Uva-116 - Unidirectional TSP(多阶段决策问题——多段图的最短路)

原题链接: uva-116

在这里插入图片描述
测试样例

Sample Input
5 6
3 4 1 2 8 6
6 1 8 2 7 4
5 9 3 9 9 5
8 4 1 3 2 6
3 7 2 8 6 4
5 6
3 4 1 2 8 6
6 1 8 2 7 4
5 9 3 9 9 5
8 4 1 3 2 6
3 7 2 1 2 3
2 2
9 10 9 10
Sample Output
1 2 3 4 4 5
16
1 2 1 5 4 5
11
1 1
19

题意: 给你一个 n n n m m m列的整数矩阵,从第一列的任何一个位置出发每次往右、右上或右下走一格,最终到达最后一列,要求经过的整数之和最小。整个矩阵是环形的,即第一行的上一行是最后一行,最后一行的下一行是第一行。输出路径上每一列的行号。多解时要求字典序最小的。

解题思路: 我们观察一下这个题目,这个整数矩阵上的每个位置就是一种状态,而我们可以选择的决策有三,向右,向右上,向右下。所以这个题起始很明显的告诉了我们该怎么做,而状态转移方程自然也是简单的,往整数和最小优化。 这里要注意的一点就是要求同解的情况下输出字典序小的,所以我们要优先考虑行号小的,这我们自然可以在决策的时候就可以判断,即先考虑行号小的。那么由于我们需要输出路径,且初始状态我们并不清楚,那么我们可以逆推思考解题(这样我们记录路径完之后就可以顺向输出)。用 d p ( i , j ) dp(i,j) dp(i,j)表示在此位置到最后一列的最少开销。那么逆推回去即可得解。注意推到第一列的时候保存最优解以及最优解的出发行号。具体看AC代码。

AC代码

/*
*blog:https://blog.csdn.net/hzf0701
*邮箱:unique_powerhouse@qq.com
*注:文章若有任何问题请私信我或评论区留言,谢谢支持。
*/
#include<bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)

using namespace std;

typedef long long ll;
const int maxn=1e5;//数组所开最大值
const int mod=1e9+7;//模
const int inf=0x3f3f3f3f;//无穷大

int d[15][105];
int g[15][105];
int Next[15][105];
int n,m;
void solve(){
    int ans=inf,first=0;//first确定起始。列。
    for(int j=m-1;j>=0;j--){
        for(int i=0;i<n;i++){
            if(j==m-1){
                d[i][j]=g[i][j];//由于是边界,没有选择。
            }
            else{
                int row[3]={i,i-1,i+1};
                if(i==0){
                    row[1]=n-1;
                }
                if(i==n-1){
                    row[2]=0;
                }
                sort(row,row+3);//字典序小的优先。
                d[i][j]=inf;
                rep(k,0,2){
                    int temp=d[row[k]][j+1]+g[i][j];//获取和。
                    if(temp<d[i][j]){
                        d[i][j]=temp;
                        Next[i][j]=row[k];;
                    }
                }
            }
            if(j==0&&d[i][j]<ans){
                //保存出发点。
                ans=d[i][j];
                first=i;
            }
        }
    }
    cout<<first+1;
    for(int i=Next[first][0],j=1;j<m;i=Next[i][j],j++){
        cout<<" "<<i+1;
    }
    cout<<'\n'<<ans<<endl;
}
int main(){
    while(cin>>n>>m){
        rep(i,0,n-1){
            rep(j,0,m-1){
                cin>>g[i][j];
            }
        }
        solve();
    }
    return 0;
}

posted @   unique_pursuit  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示