紫书第九章-----动态规划初步(例题9-4 Unidirectional TSP UVA - 116 )

【AC代码分享】
本题是简单的动态规划问题,但是打印出字典序最小的路径笔者费了一番周折!笔者特别处理了遇到多解时要输出最小字典序的问题。详见代码如下:

/*
d(i,j)表示从位置(i,j)出发的最短路径
d(i,j)=min{d(i-1,j+1),d(i,j+1),d(i+1,j+1)}
*/

#include<bits/stdc++.h>
using namespace std;

const int maxn=1005;

int m,n;
int a[maxn][maxn];
int d[maxn][maxn];
int path_next[maxn][maxn];

int main()
{
    while(cin>>m>>n){
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                cin>>a[i][j];
            }
        }
        for(int i=1;i<=m;i++){
            d[i][n]=a[i][n];
        }
        for(int j=n-1;j>=1;j--){
            for(int i=1;i<=m;i++){
                int r1=(i==1?m:i-1);
                int r2=i;
                int r3=(i==m?1:i+1);
                int v1=d[r1][j+1];
                int v2=d[r2][j+1];
                int v3=d[r3][j+1];
                //因为要打印出最短路径,下面分了几种情况全面讨论
                if(v1==v2 && v1==v3){
                    path_next[i][j]=min(r1,min(r2,r3));//第j列i行下一个是第j+1列的r2,r3中的较小值,下类似
                    d[i][j]=a[i][j]+v1;
                }
                else if(v3<=v2 && v3<=v1){
                    path_next[i][j]=r3;
                    if(v3==v2){
                        path_next[i][j]=min(r2,r3);
                    }
                    if(v3==v1){
                        path_next[i][j]=min(r3,r1);
                    }

                    d[i][j]=a[i][j]+v3;
                }
                else if(v2<=v1 && v2<=v3){
                    path_next[i][j]=r2;
                    if(v2==v1){
                        path_next[i][j]=min(r1,r2);
                    }
                    if(v2==v3){
                        path_next[i][j]=min(r2,r3);
                    }
                    d[i][j]=a[i][j]+v2;
                }
                else if(v1<=v2 && v1<=v3){
                    path_next[i][j]=r1;
                    if(v1==v2){
                        path_next[i][j]=min(r1,r2);
                    }
                    if(v1==v3){
                        path_next[i][j]=min(r1,r3);
                    }
                    d[i][j]=a[i][j]+v1;
                }
            }
        }
        int ans=d[1][1];
        int mark=1;
        //找到最小字典序的解对应的第一列的行
        for(int i=1;i<=m;i++){
            if(ans>d[i][1]){
                ans=d[i][1];
                mark=i;
            }
        }
        cout<<mark;
        int cnt=0;
        while(++cnt<n){
            cout<<" "<<path_next[mark][cnt];//注意末尾不要多输出一个空格,否则Presentation Error
            mark=path_next[mark][cnt];
        }
        cout<<endl;
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ccnuacmhdu/article/details/81209166