UVA116----简单的DP,但是输出路径比较坑

来源:互联网 发布:java 树深度遍历 编辑:程序博客网 时间:2024/05/05 23:19

题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=52

这是一道比较简单的DP

题意就是在一个n*m的矩阵,每一(i,j)都有一个值

从第1列到第m列,要你找一条路径出来

使得相加的和最少

可以往后一列的行-1,当前行,行+1

如果是在边界行,则可以循环,题目中说的比较清楚

这一看就是很明显的DP,但是有一个问题

输出路径的时候如果有多条路径,输出字典序最小的那个

如果从前往后递推的话,那么最后保存答案的时候就要从后面往前

但是字典序是从第一个开始比较的,所以你不清楚你的到底会不会是最小的字典序

那么我们就把这个倒过来

从后往前递推,保存答案的时候从前往后保存

这样就十分的清除,我们找的就是最小的字典序的路径

下面看我的代码:

#include<cstdio>#include<cstring>using namespace std;const int maxn = 110;int dp[maxn][maxn];int behind[maxn][maxn];int n,m;int ans[maxn];void read(){    for(int i=0;i<n;i++)    {        for(int j=0;j<m;j++)            scanf("%d",&dp[i][j]);    }}void solve(){    for(int j=m-2;j>=0;j--)    {        for(int i=0;i<n;i++)        {            int up = i-1;            int mid = i;            int down = (i+1)%n;            if(i==0)            {                up = n-1;                if(dp[mid][j+1]<=dp[up][j+1] && dp[mid][j+1]<=dp[down][j+1])                {                    dp[i][j]+=dp[mid][j+1];                    behind[i][j] = mid;                }                else if(dp[down][j+1]<=dp[up][j+1] && dp[down][j+1]<=dp[mid][j+1])                {                    dp[i][j]+=dp[down][j+1];                    behind[i][j] = down;                }                else if(dp[up][j+1]<=dp[down][j+1] && dp[up][j+1]<=dp[mid][j+1])                {                    dp[i][j]+=dp[up][j+1];                    behind[i][j] = up;                }            }            else if(i==n-1)            {                if(dp[down][j+1]<=dp[up][j+1] && dp[down][j+1]<=dp[mid][j+1])                {                    dp[i][j]+=dp[down][j+1];                    behind[i][j] = down;                }                else if(dp[up][j+1]<=dp[down][j+1] && dp[up][j+1]<=dp[mid][j+1])                {                    dp[i][j]+=dp[up][j+1];                    behind[i][j] = up;                }                else if(dp[mid][j+1]<=dp[up][j+1] && dp[mid][j+1]<=dp[down][j+1])                {                    dp[i][j]+=dp[mid][j+1];                    behind[i][j] = mid;                }            }            else            {                if(dp[up][j+1]<=dp[down][j+1] && dp[up][j+1]<=dp[mid][j+1])                {                    dp[i][j]+=dp[up][j+1];                    behind[i][j] = up;                }                else if(dp[mid][j+1]<=dp[up][j+1] && dp[mid][j+1]<=dp[down][j+1])                {                    dp[i][j]+=dp[mid][j+1];                    behind[i][j] = mid;                }                else if(dp[down][j+1]<=dp[up][j+1] && dp[down][j+1]<=dp[mid][j+1])                {                    dp[i][j]+=dp[down][j+1];                    behind[i][j] = down;                }            }        }    }    int min = 0x3f3f3f;    int min2;    for(int i=0;i<n;i++)    {        if(dp[i][0]<min)        {            min = dp[i][0];            min2 = i;        }    }    ans[0] = min2;    for(int i=1;i<m;i++)    {        ans[i] = behind[ans[i-1]][i-1];    }    for(int i=0;i<m;i++)    {        if(!i)            printf("%d",ans[i]+1);        else            printf(" %d",ans[i]+1);    }    printf("\n%d\n",min);}void out(){    printf("----------------------------------\n");    for(int i=0;i<n;i++)    {        for(int j=0;j<m;j++)            printf("%d ",dp[i][j]);        printf("\n");    }    printf("----------------------------------\n");}int main(){    while(~scanf("%d%d",&n,&m))    {        read();        //out();        solve();        //out();    }}