poj 2353 双向DP

来源:互联网 发布:美工设计初级视频 编辑:程序博客网 时间:2024/05/01 22:51

水题。

从左和上到右扫一遍,在从右到左扫一遍,记录下最小的值和路径。path[i][j]记录是从哪个方向转移的。这样就ok了~

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define INF 1e13int M,N;int map[111][555];__int64 dp[111][555];int path[111][555];int p[50000];void init(){    int i,j;    for(i=0;i<=N+1;i++)    {        dp[0][i]=INF;    }    for(i=0;i<=M+1;i++)    {        dp[i][0]=INF;        dp[i][N+1]=INF;    }    for(i=1;i<=N;i++)    {        dp[1][i]=map[1][i];        path[1][i]=1;    }}void DP(){    int i,j;    for(i=2;i<=M;i++)    {        for(j=1;j<=N;j++)        {            if(dp[i][j-1]<dp[i-1][j])            {                dp[i][j]=map[i][j]+dp[i][j-1];                path[i][j]=2;            }            else            {                dp[i][j]=map[i][j]+dp[i-1][j];                path[i][j]=1;            }            //dp[i][j]=map[i][j]+Min(dp[i][j-1],dp[i-1][j]);        }        for(j=N;j;j--)        {            if(dp[i][j]>map[i][j]+dp[i][j+1])            {                dp[i][j]=map[i][j]+dp[i][j+1];                path[i][j]=3;            }        }    }}void print(){    int i,j,posi,posj;    __int64 Min=INF;    for(i=1;i<=N;i++)    {        if(dp[M][i]<Min)        {            Min=dp[M][i];            posi=M;            posj=i;        }    }    int len=0;    p[len++]=posj;    while(path[posi][posj])    {        if(path[posi][posj]==1)        {            p[len++]=posj;            posi--;        }        if(path[posi][posj]==2)        {            posj--;            p[len++]=posj;        }        if(path[posi][posj]==3)        {            posj++;            p[len++]=posj;        }    }    for(len-=2;len>=0;len--)    {        printf("%d\n",p[len]);    }}int main(){    int i,j;    scanf("%d%d",&M,&N);    for(i=1;i<=M;i++)    {        for(j=1;j<=N;j++)        {            scanf("%d",&map[i][j]);        }    }    init();    DP();    print();    return 0;}


 

0 0
原创粉丝点击