BNU4206:单向行走

给定一个m*n的矩阵,请写一个程序计算一条从左到右走过矩阵且权和最小的路径。一条路径可以从第1列的任意位置出发,到达第n列的任意位置。每一步只能从第i列走到第i+1列的同一行或者相邻行(第一行和最后一行看作是相邻的)。

 
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
 
例如1 -> 2 -> 23 -> 24 ->25就是一条路径。
路径的权和为所有经过的n个方格中整数的和。

Input

 输入数据包含一个矩阵。

输入数据的第一行为两个数,m和n,分别表示矩阵的行数和列数。(0<m*n<=10000)
接下来m*n个整数按照行优先的顺序依次排列。
 

Output

 输出数据包含两行。

第一行给出一个整数,为最小路径的权值。
第二行给出最小路径上从左到右依次经过的行号,有多个最小路径时输出字典序最小的一条。
 
 

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 1 2 3

 

Sample Output

11

1 2 1 5 4 5
 
#include <stdio.h>

#include <string.h>

#include <algorithm>

using namespace std;



int a[10005][10005];

int path[10005][10005];

const int inf = 99999999;



int main()

{

    int n,m,i,j,ans,to,v,k,p;

    while(~scanf("%d%d",&n,&m))

    {

        for(i = 0; i<n; i++)

            for(j = 0; j<m; j++)

                scanf("%d",&a[i][j]);

        for(i = m-2; i>=0; i--)//从第m-2列开始,枚举所有状况

        {

            for(j = 0; j<n; j++)

            {

                int minn = inf,id = inf;

                for(to = -1; to<=1; to++)

                {

                    v = a[(j+to+n)%n][i+1];

                    p = (j+to+n)%n;

                    if(minn>v || (minn == v && p<id))//找出最小路径,相同则找字典序小的

                    {

                        minn = v;

                        id = p;

                    }

                }

                a[j][i]+=minn;

                path[j][i] = id;

            }

        }

        ans = inf;

        for(i = 0; i<n; i++)

        {

            if(ans>a[i][0])

            {

                ans = a[i][0];

                k = i;

            }

        }

        printf("%d\n%d",ans,k+1);

        for(i = 0; i<m-1; i++)

        {

            printf(" %d",path[k][i]+1);

            k = path[k][i];

        }

        printf("\n");

    }



    return 0;

}

你可能感兴趣的:(B)