Unidirectional TSP UVA - 116

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

思路:设d(i,j)为从格子(i,j)出发到最后一列的最小开销。在计算d(i,j)的同时记录“下一列的行号”的最小值(在满足最优解的前提下)

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mod 1000000007;
using namespace std;
const int maxn = 102;
int n,m,nex[12][maxn];
int d[12][maxn],a[12][maxn];
int main()
{
    while(scanf("%d%d",&n,&m) != EOF)
    {
        int first = 0,ans = INF;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
                scanf("%d",&a[i][j]);
        }
        for(int i = m - 1; i >= 0; i--) //列
        {
            for(int j = 0; j < n; j++) //行
            {
                if(i == m - 1)
                {
                    d[j][i] = a[j][i];
                }
                else
                {
                    d[j][i] = INF;
                    int row[] = {j - 1,j,j + 1};
                    if(j == 0) row[0] = n - 1;
                    if(j == n - 1) row[2] = 0;
                    sort(row,row + 3);
                    for(int k = 0; k < 3; k++)
                    {
                        int v = d[row[k]][i + 1] + a[j][i];
                        if(v < d[j][i])
                        {
                            d[j][i] = v;
                            nex[j][i] = row[k];
                        }
                    }
                }
                if(i == 0 && d[j][i] < ans)
                {
                    ans = d[j][i];
                    first = j;
                }
            }
        }
        printf("%d",first + 1);
        for(int i = nex[first][0],j = 1; j < m; i = nex[i][j],j++)
        {
            printf(" %d",i + 1);
        }
        printf("\n%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值