HDU 1619 Unidirectional TSP (dp,dfs)

题目大意:要求从左边到右边(注意第1行和最后一行相邻),即:从第1列到最后一列即可,共有三种走法,求最小的代价及打印行号。

          三种走法,


Sample Input
5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 8 6 4 5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 1 2 3 2 2 9 10 9 10
 

Sample Output
1 2 3 4 4 5 16 1 2 1 5 4 5 11 1 1 19


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 222
#define inf 1<<30
int map[MAXN][MAXN];
int dp[MAXN][MAXN];
int n,m,len;
int path[MAXN];


int dfs(int x, int y)
{
    if(dp[x][y]!=inf)
        return dp[x][y];
    if(y==m-1)
        return dp[x][y]=map[x][y];
    int ans=min(min(dfs((x-1+n)%n,y+1),dfs(x,y+1)),dfs((x+1)%n,y+1));
    return dp[x][y]=ans+map[x][y];
}


void Solve(int x, int y)
{
    path[len++]=x;
    if(y==m-1)return ;
    int x1=(x-1+n)%n, x2=x, x3=(x+1)%n;
    for(int i=0;i<n;i++)
    {
        if(dp[x][y]==dp[i][y+1]+map[x][y]&&(i==x1||i==x2||i==x3))
        {
            Solve(i,y+1);
            return ;
        }
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(dp,0,sizeof(dp));
        
        for(int i=0;i<=n;i++)
            for(int j=0;j<=m;j++)
                dp[i][j]=inf;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                scanf("%d",&map[i][j]);
                
        int ans=inf,pos;
        for(int i=0;i<n;i++)
        {
            if(dfs(i,0)<ans)
            {
                ans=dp[i][0];
                pos=i;
            }
        }
        
        len=0;
        Solve(pos,0);//从第一列的第pos行往后找路径(dp[pos][0]即为最小值)
        
        printf("%d",path[0]+1);
        for(int i=1;i<len;i++)
            printf(" %d",path[i]+1);
        printf("\n%d\n",ans);
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

posted on 2015-05-09 11:05  王老大-  阅读(185)  评论(0编辑  收藏  举报

导航