UVA - 116 Unidirectional TSP

题目地址

给一个m*n的矩阵 每个格子有一个值 输出一种走到最后一列的走法,使得路过的格子的值的和最小且字典序最小。

设d[i][j]为从(i,j)到最后一列的最小开销,那么最后一列的格子的d值就是格子本身的值。每一次有三种决策:右上、直右和右下,一步步推就行。

为了保存最小字典序,排序是必要的。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;


const int INF=0x3f3f3f3f;

int a[110][110],Next[110][110],dp[110][110];
int main()
{
    int n,m;
    while(cin>>m>>n&&m)
    {
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                scanf("%d",&a[i][j]);

        int ans=INF,first=0;

        for(int j=n-1;j>=0;j--)
        {
            for(int i=0;i<m;i++)
            {
                if(j==n-1) dp[i][j]=a[i][j];
                else
                {
                    int rows[3]={i,i-1,i+1};
                    if(i==0) rows[1]=m-1;
                    if(i==m-1) rows[2]=0;
                    sort(rows,rows+3);
                    dp[i][j]=INF;

                    for(int k=0;k<3;k++)
                    {
                        int v=dp[rows[k]][j+1]+a[i][j];
                        if(v<dp[i][j]) { dp[i][j]=v;Next[i][j]=rows[k]; }
                    }
                }
                if(j==0&&dp[i][j]<ans) { ans=dp[i][j];first=i; }
            }

        }
        cout<<first+1;
        for(int i=Next[first][0],j=1;j<n;i=Next[i][j],j++)
            cout<<' '<<i+1;
        cout<<endl<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41333002/article/details/81459991