UVa 116 - Unidirectional TSP(dp)

题意:找最短路,知道三种行走方式,给出图,求出一条从左边到右边的最短路,且字典序最小。

思路:用dp记忆化搜索的思想来考虑是思路很清晰的,状态方程:max{ dp[i+1,j+1], dp[i,j+1], dp[i-1,j+1]},

但是困难在如何求出字典序最小的路。

因为左边到右边的字典序最小就必须从左边开始找,于是我们可以换个思路,dp时从右边走到左边,这样寻找路径就可以从左向右了。


#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<map>

#define N 100010
#define Mod 10000007
#define lson l,mid,idx<<1
#define rson mid+1,r,idx<<1|1
#define lc idx<<1
#define rc idx<<1|1
const double EPS = 1e-11;
const double PI = acos(-1.0);
const double E=2.718281828;
typedef long long ll;

const int INF=2147483647;

using namespace std;

int a[11][110];
int d[12][120],next[120][110];

int main()
{
    //freopen("in.txt","r",stdin);
    int n,m;
    while(cin>>m>>n)
    {
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
                scanf("%d",&a[i][j]);
        int ans=INF,first=0;
        //cout<<ans<<endl;
        for(int j=n-1; j>=0; j--)
        {
            for(int i=0; i<m; i++)
            {
                if(j==n-1)
                    d[i][j]=a[i][j];
                else
                {
                    int row[3]= {i,i-1,i+1};
                    if(i==0)
                        row[1]=m-1;
                    if(i==m-1)
                        row[2]=0;
                    sort(row,row+3);
                    d[i][j]=INF;
                    for(int k=0; k<3; k++)
                    {
                        int v=d[row[k]][j+1]+a[i][j];
                        if(v<d[i][j])
                            d[i][j]=v,next[i][j]=row[k];
                    }
                }
                if(j==0&&d[i][j]<ans)
                    ans=d[i][j],first=i;
            }
        }
        printf("%d",first+1);
        for(int i=next[first][0],j=1; j<n; i=next[i][j],j++)
            printf(" %d",i+1);
        printf("\n%d\n",ans);
    }
    return 0;
}
相关文章
相关标签/搜索