街道问题 (DP)

来源:互联网 发布:2017免费下载农村淘宝 编辑:程序博客网 时间:2024/06/10 15:04


如图所示的矩形图中找到一条从左下角到右上角的最短路径,图中数字表示边的长度。只能向右或向上走。

【输入文件】第一行两个数,N矩形的点有NM列。(0<NM<1000)接下来N行每行M-1个数描述横向边的长度。接下来N-1行每行M个数描述纵向边的长度。边的长度小于10

【输出文件】一个数——最短路径长度。

【输入样例】

4 5

3 7 4 8

4 6 3 5

3 6 3 5

5 4 6 2

7 6 3 5 3

2 8 5 9 4

8 7 4 3 7

【输出样例】

28



        

   首先考虑穷举情况,只考虑步数,因为只能往上或右走,则要走m+n步,那么所有的情况为在(m+n)步中选择m步向右走,即 可能的方案数为 C(m+n , m),如果m和n可以达到1000的话,肯定是不行的。

   我们很快可以发现,如果在最底边,并且从一开始只往右走,那么最小的代价一定是往右走的代价和,如上图,底边1到m个点中,从左到右的代价依次为0,5,9,15,17。

同理最左边的边界从1到n的代价为0,8,10,17。那么开始考虑不是边界的情况,假设dp[i][j]代表从一开始到(i,j)的最小代价,它只能由(i-1,j)向上走或是(i,j-1)向右走得到,那么状态转移方程很容易写出:

                          dp[i][j]=min(dp[i-1][j]+up[i][j] , dp[i][j-1]+right[i][j])      ( 2<=i<=n , 2<=j<=m )

                          dp[1][i]=right[1][i]  ( 2<=i<=m  )

                          dp[i][1]=up[i][1]  (  2<=i<=n )

其中,right[][]代表向右走的代价,up[][]代表向上走的代价。dp[n][m]即为总代价。


#include<stdio.h>int n,m,r[1003][1003],u[1003][1003],dp[1003][1003];int Min(int a,int b){    return a<b?a:b;}int main(){    while(~scanf("%d%d",&n,&m))    {        int i,j;        for(i=n;i>=1;i--)            for(j=2;j<=m;j++)                scanf("%d",&r[i][j]);        for(i=n;i>=2;i--)            for(j=1;j<=m;j++)                scanf("%d",&u[i][j]);        dp[1][2]=r[1][2];               //初始化边界        for(i=3;i<=m;i++)            dp[1][i]=dp[1][i-1]+r[1][i];        dp[2][1]=u[2][1];        for(i=3;i<=n;i++)            dp[i][1]=dp[i-1][1]+u[i][1];        for(i=2;i<=m;i++)               //DP            for(j=2;j<=n;j++)                dp[j][i]=Min(dp[j-1][i]+u[j][i],dp[j][i-1]+r[j][i]);        printf("%d\n",dp[n][m]);    }    return 0;}



2 0
原创粉丝点击