题解:uva116 多段图tsp

题目大意:

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

输入有若干组数据:

每组的第1行:m和n,分别为行数和列数。

每组的第2~m+1行:每行n个数,用空格分开,代表整数矩阵。

输出:

每组有两行,第一行是每列的行号,第二行是路径的经过的整数之和。

解题思路:

设dp[i][j]表示从i,j格子出发到最后一列的最小开销,并记录后一列的行号

调试记录:

memset付初始值得时候有问题,赋的值不够大导致wa,将INF改为0x3f3f3f即可

下面看代码

 1#include<bits/stdc++.h>
2using namespace std;
3int mat[40][405],dp[40][405],n,m,path[50][505],cost,INF;
4int main(){
5     INF=0x3f3f3f3f
6     while (scanf("%d%d",&n,&m)==2){
7         for (int i=1;i<=n;i++)
8             for (int j=1;j<=m;j++)
9                 scanf("%d",&mat[i][j]);
10        memset(dp,INF,sizeof(dp));
11        for (int i=1;i<=n;i++) dp[i][m]=mat[i][m]; 
12        for (int j=m;j>1;j--){//逆推转移
13            for (int i=1;i<=n;i++){
14                int row[3];//可以走过来的三方向
15                row[0]=i-1;row[1]=i;row[2]=i+1;
16                if (i==1) row[0]=n;
17                if (i==n) row[2]=1;
18                sort(row,row+3);//排序保证字典序最小
19                for (int x=0;x<3;x++){
20                    int tmp=dp[i][j]+mat[row[x]][j-1];
21                    if (tmp<dp[row[x]][j-1]){
22                        dp[row[x]][j-1]=tmp;
23                        path[row[x]][j-1]=i; 
24                    }
25
26                } 
27            }
28        }
29        int cost=INF,r;
30        for (int i=1;i<=n;i++)
31            if (cost>dp[i][1])
32                r=i,cost=dp[i][1];
33        printf("%d",r);
34        for(int i = path[r][1],j=1;j<m;j++,i = path[i][j])
35             printf(" %d", i);
36        printf("\n%d\n",cost);
37     }
38    return 0;
39
原文地址:https://www.cnblogs.com/titititing/p/9514580.html