HDU 5569 matrix

5569 matrix

记得在动态规划那里有个很经典的题目是给一个数字矩阵n*m,每个位置上有权值,从(1,1)走到(n,m)的最值问题。而这道题是让你把走过的数字按照a1,a2,...,a2k.按照a1∗a2+a3∗a4+...+a2k−1∗a2k计算,使计算的结果最小。

dp(i,j)=在坐标(i,j)的点最小值

我的思路也是DP,因为题目要求只能往右边和下边移动,所以可以预处理一下可以达到dp(i,j)的点就行了。首先把第一行和第一列预处理出来,然后边界情况特殊处理一下。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,m;
int mapp[1010][1010],dp[1010][1010];//第i行第j列。
void inint(int i,int j)
{

    if((i+j)%2==1)
    {
        int rr,cc;
        if(j>2)
            rr=min(mapp[i][j]*mapp[i][j-1]+dp[i][j-2],mapp[i][j]*mapp[i][j-1]+dp[i-1][j-1]);
        else
            rr=mapp[i][j]*mapp[i][j-1]+dp[i-1][j-1];
        if(i>2)
            cc=min(mapp[i][j]*mapp[i-1][j]+dp[i-2][j],mapp[i][j]*mapp[i-1][j]+dp[i-1][j-1]);
        else
            cc=mapp[i][j]*mapp[i-1][j]+dp[i-1][j-1];
        dp[i][j]=min(rr,cc);
    }
    else
    {
        dp[i][j]=min(dp[i-1][j],dp[i][j-1]);
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                scanf("%d",&mapp[i][j]);
        dp[1][1]=mapp[1][1];
        for(int i=2; i<=m; i++)//处理第一行
        {
            if(i%2==0)
                dp[1][i]=dp[1][i-2]+mapp[1][i-1]*mapp[1][i];
            else
                dp[1][i]=dp[1][i-1]+mapp[1][i];
        }
        for(int i=2; i<=n; i++)//处理第一列
        {
            if(i%2==0)
                dp[i][1]=dp[i-2][1]+mapp[i-1][1]*mapp[i][1];
            else
                dp[i][1]=dp[i-1][1]+mapp[i][1];
        }


        for(int i=2; i<=n; i++)
        {
            for(int j=2; j<=m; j++)
            {
                inint(i,j);
            }
        }
        /*for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
                printf("%d ",dp[i][j]);
            printf("\n");
        }*/
        printf("%d\n",dp[n][m]);
    }
    return 0;
}
posted @ 2015-11-23 18:45  zzuli_柚子  阅读(198)  评论(0编辑  收藏  举报