单向TSP(unidirectional TSP,UVa 116)

来源:互联网 发布:linux环境变量是什么 编辑:程序博客网 时间:2024/05/13 15:18

问题:
给你一个n行m列的整数矩形,从第一列任何一个位置出发每次往右,右上或右下走一格,最终到达最后一列。要求经过的整数之和最小,整个矩形是环形的,即第一行的上一行是最后一行,最后一行的下一行是第一行,输出路径上每列的行号,多解时输出字典序最小的。
分析:
每一列就是一个状态,这个状态是由前一列的右上,右,右下得到的,要得到每个状态的最小值,只需比较右上,右,右下的最小值就好了。就得得到了下面的状态转移方程:

dp[i][j]=dp[i][j]+min(dp[i-1][j-1],dp[i][j-1],dp[i+1][j-1]);

在输出最小字典序的时候,可以采用之前用过的方法。
代码:

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>using namespace std;const int maxx=10000;int G[maxx][maxx];int dp[maxx][maxx];int n,m,ar[3];int compare_min(int a,int b,int c)   //比较a,b,c中最小的一个{     ar[0]=a,ar[1]=b,ar[2]=c;     sort(ar,ar+3);     return ar[0];}int main(){     cin>>n>>m;     for(int i=1;i<=n;i++)          for(int j=1;j<=m;j++)               cin>>G[i][j];     for(int j=0,i=1;i<=n;i++)          dp[i][j]=0;     for(int j=1;j<=m;j++)          for(int i=1;i<=n;i++)          {               if(i==1)                    dp[i][j]=G[i][j]+compare_min(dp[n][j-1],dp[i][j-1],dp[i+1][j-1]);               else if(i==n)                    dp[i][j]=G[i][j]+compare_min(dp[i-1][j-1],dp[i][j-1],dp[1][j-1]);               else                    dp[i][j]=G[i][j]+compare_min(dp[i-1][j-1],dp[i][j-1],dp[i+1][j-1]);          }     int ans=(1<<30);     for(int j=m,i=1;i<=n;i++)          if(ans>dp[i][j])               ans=dp[i][j];     cout<<ans<<endl;     int road[m],cns=0;     for(int j=m;j>=1;j--)     {          for(int i=1;i<=n;i++)          {               if(dp[i][j]==ans)               {                    road[cns]=i;                    break;               }          }          ans=ans-G[road[cns]][j];          cns++;     }     for(int i=m-1;i>=0;i--)          cout<<road[i]<<" ";;     cout<<endl;     return 0;}

感觉这个问题很简单,是自己独立想出来的,也是独立的写完了自己的代码,继续努力。书上的方法好像不一样我再研究一下。

0 0
原创粉丝点击