欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[中等] UVa OJ 116 Unidirectional TSP 动态规划

程序员文章站 2024-01-19 14:46:34
...

题目描述

基本思路:

首先这是一个多阶段决策问题,所以考虑采用动态规划来解。而题目最后输出路径时要求按字典序,所以从后向前进行迭代求解。

状态转移方程:d[i][j]=cost[i][j]+min{d[i-1][j+1],d[i][j+1],d[i+1][j+1]}。不过此处要注意因为允许“wrap",所以当i-1应为(i-1+m)%m,而i+1应为(i+1)%m

然后对于如何打印路径,可以多开一个数组next[maxm][maxn]来保存路径中当前列的下一列的行数。也可以采用从前向后找的方法。下面代码中采用了第二种方法(从前向后找)。

注意打印行数时的编码技巧,rows数组的使用

具体代码:

#include <iostream>
#include <algorithm>
#include <climits>

using namespace std;
const int maxm=10+2;
const int maxn=100+3;
int c[maxm][maxn];
long long d[maxm][maxn];
int main()
{
   // freopen("input.txt","r",stdin);
    int m,n;
    while(cin>>m>>n)
    {
        for(int i=0;i<m;++i)
            for(int j=0;j<n;++j)
            {
                cin>>c[i][j];
                d[i][j]=LLONG_MAX;
            }
        for(int i=0;i<m;++i)
            d[i][n-1]=c[i][n-1];
        for(int j=n-2;j>=0;--j)
        {
            for(int i=0;i<m;++i)
            {
                d[i][j]=c[i][j]+min(min(d[(i-1+m)%m][j+1],d[i][j+1]),d[(i+1)%m][j+1]);
            }
        }
        long long ans=d[0][0];
        int lasti=0;
        for(int i=1;i<m;++i)
        {
            if(d[i][0]<ans)
            {
                ans=d[i][0];
                lasti=i;
            }
        }
        cout<<lasti+1;
        for(int j=1;j<n;++j)
        {
            int rows[3]={(lasti-1+m)%m,lasti,(lasti+1)%m};
            sort(rows,rows+3);
            for(int i=0;i<3;++i)
                if(d[rows[i]][j]+c[lasti][j-1]==d[lasti][j-1])
                {
                    cout<<" "<<rows[i]+1;
                    lasti=rows[i];
                    break;
                }
            //The code below can also print the right path, but it is a little complex and not concise.
            /*if(lasti+1>=m&&d[0][j]==d[lasti][j-1]-c[lasti][j-1])
            {
                lasti=0;
                cout<<" 1";
            }
            else if(lasti-1>=0&&d[lasti-1][j]==d[lasti][j-1]-c[lasti][j-1])
            {
                cout<<" "<<lasti;
                --lasti;
            }
            else if(d[lasti][j]==d[lasti][j-1]-c[lasti][j-1])
            {
                cout<<" "<<lasti+1;
            }
            else if(d[lasti+1][j]==d[lasti][j-1]-c[lasti][j-1])
            {
                cout<<" "<<lasti+2;
                ++lasti;
            }
            else
            {
                cout<<" "<<m;
                lasti=m-1;
            }*/
        }
        cout<<endl;
        cout<<ans<<endl;
    }
    return 0;
}