现在的位置: 首页 > 综合 > 正文

dp uva-116-Unidirectional TSP

2013年11月05日 ⁄ 综合 ⁄ 共 1771字 ⁄ 字号 评论关闭

 

题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=52

 

题目意思:

给你一个矩阵,让你求从第一列到最后一列的所有路径中值最小的那个,其中可以向上一行或当行或下一行走,其中最后一行和第一行可以看成相邻的。如果有多条值相同的路径,要求保证按字典顺序最小的输出路径。

 

解题思路:

从右向左依次动态规划,并保存路径。这样可以保证最后路径输出的是字典序最小的。

 

详见代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define eps 1e-6
#define INF (1<<20)
#define PI acos(-1.0)
using namespace std;


int save[15][120];
int dp[120][15],path[120][15],m,n;  //dp[i][j]表示从最后一列到第i列第j行为止最小的值
                                //相应的path[i][j]表示到达第i列第j行的后一列的行数
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        memset(path,-1,sizeof(path));
        memset(dp,0,sizeof(dp));

        for(int i=1;i<=m;i++)
        {
            int j;
            for(j=1;j<n;j++)
                scanf("%d",&save[i][j]);
            scanf("%d",&save[i][j]);
            dp[j][i]=save[i][j];   //初始化
        }

        for(int i=n-1;i>=1;i--)
        {                                 //先考虑第一行的情况
            dp[i][1]=dp[i+1][1];          //注意比较的顺序
            path[i][1]=1;
            if(m>1&&dp[i+1][2]<dp[i][1])  //注意考虑只有一行的情况,m>1不能省略
            {
                dp[i][1]=dp[i+1][2];
                path[i][1]=2;
            }
            if(dp[i+1][m]<dp[i][1])
            {
                dp[i][1]=dp[i+1][m];
                path[i][1]=m;
            }
            dp[i][1]+=save[1][i];

            for(int j=2;j<m;j++)  //考虑第二行到倒数第二行的情况,此时情况都一样,可以统一处理
            {
                dp[i][j]=dp[i+1][j-1];
                path[i][j]=j-1;
                if(dp[i+1][j]<dp[i][j])
                {
                    dp[i][j]=dp[i+1][j];
                    path[i][j]=j;
                }
                if(dp[i+1][j+1]<dp[i][j])
                {
                    dp[i][j]=dp[i+1][j+1];
                    path[i][j]=j+1;
                }
                dp[i][j]+=save[j][i];
            }

            dp[i][m]=dp[i+1][1];        //考虑最后一行的情况
            path[i][m]=1;
            if(m>1&&dp[i+1][m-1]<dp[i][m]) //注意考虑只有一行的情况,m>1不能省略
            {
                dp[i][m]=dp[i+1][m-1];
                path[i][m]=m-1;
            }
            if(dp[i+1][m]<dp[i][m])
            {
                dp[i][m]=dp[i+1][m];
                path[i][m]=m;
            }
            dp[i][m]+=save[m][i];
        }

        int sum=dp[1][1],begin=1;

        for(int i=2;i<=m;i++)    //统计最少的那条路径
        {
            if(dp[1][i]<sum)
            {
                sum=dp[1][i];
                begin=i;
            }
        }

        printf("%d",begin);
        int temp=1;
        while(path[temp][begin]!=-1)   //输出路径
        {
            printf(" %d",path[temp][begin]);
            begin=path[temp][begin];
            temp++;
        }
        printf("\n%d\n",sum);    //输出最小的和

    }
    return 0;
}




 

【上篇】
【下篇】

抱歉!评论已关闭.