HDU 5092

http://acm.hdu.edu.cn/showproblem.php?pid=5092

卡读题,实质是每行取一个点,从上到下找一条路径权值和最小,点可以到达的地方是周围八个格子

类似数塔的dp,需要记录路径,当前行由上一行顶上的三个格子转移而来

#include <iostream>

#include <cstdio>

#include <queue>

#include <cstring>

#include <algorithm>

#include <stack>



using namespace std;

int n,m;

int a[105][105],dp[105][105],pre[105][105];

int dx[]={-1,-1,-1};

int dy[]={0,1,-1};



struct node{

    int x,y;

};



int main(){

    int T;

    scanf("%d",&T);

    for(int cas=1;cas<=T;cas++){

        scanf("%d%d",&n,&m);

        for(int i=1;i<=n;i++){

            for(int j=1;j<=m;j++){

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

            }

        }

        for(int i=0;i<105;i++)

            for(int j=0;j<105;j++)

                dp[i][j]=0xfffffff;

        for(int i=1;i<=m;i++)

            dp[1][i]=a[1][i];

        memset(pre,-1,sizeof(pre));

        for(int i=2;i<=n;i++){

            for(int j=1;j<=m;j++){

                if(j-1>=1 && j+1<=m){

                    //dp[i][j]=min(dp[i][j],a[i][j]+min(dp[i-1][j],min(dp[i-1][j-1],dp[i-1][j+1])));

                    int t=min(dp[i-1][j],min(dp[i-1][j-1],dp[i-1][j+1]));

                    if(a[i][j]+t<dp[i][j]){

                        dp[i][j]=a[i][j]+t;

                        if(dp[i-1][j+1]<=dp[i-1][j-1] && dp[i-1][j+1]<=dp[i-1][j])

                            pre[i][j]=1;

                        else if(dp[i-1][j]<=dp[i-1][j-1] && dp[i-1][j]<=dp[i-1][j+1])

                            pre[i][j]=0;

                        else pre[i][j]=2;

                    }

                }

                else if(j-1>=1){

                    //dp[i][j]=min(dp[i][j],a[i][j]+min(dp[i-1][j],dp[i-1][j-1]));

                    int t=min(dp[i-1][j],dp[i-1][j-1]);

                    if(a[i][j]+t<dp[i][j]){

                        dp[i][j]=a[i][j]+t;

                        if(dp[i-1][j]<=dp[i-1][j-1])

                            pre[i][j]=0;

                        else pre[i][j]=2;

                    }

                }

                else if(j+1<=m){

                    //dp[i][j]=min(dp[i][j],a[i][j]+min(dp[i-1][j],dp[i-1][j+1]));

                    int t=min(dp[i-1][j],dp[i-1][j+1]);

                    if(a[i][j]+t<dp[i][j]){

                        dp[i][j]=a[i][j]+t;

                        if(dp[i-1][j+1]<=dp[i-1][j])

                            pre[i][j]=1;

                        else pre[i][j]=0;

                    }

                }

            }

        }

        int ans=0xfffffff;

        int res;

        for(int i=1;i<=m;i++){

            //ans=min(ans,dp[n][i]);

            if(ans>=dp[n][i]){

                ans=dp[n][i];

                res=i;

            }

        }

        printf("Case %d\n",cas);

        stack <node> s;

        node st;

        st.x=n;st.y=res;

        s.push(st);

        while(1){

            if(st.x==1)break;

            int xx=st.x+dx[pre[st.x][st.y]];

            int yy=st.y+dy[pre[st.x][st.y]];

            st.x=xx;st.y=yy;

            s.push(st);

        }

        for(int i=1;i<=n;i++){

            if(i==1)printf("%d",s.top().y);

            else printf(" %d",s.top().y);

            s.pop();

        }

        putchar('\n');

    }

    return 0;

}
View Code

 

你可能感兴趣的:(HDU)