dp uva-116-Unidirectional TSP

来源:互联网 发布:华云数据最新消息 编辑:程序博客网 时间:2024/06/05 02:16

 

题目链接:

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;}




 

原创粉丝点击