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("
");
}*/
printf("%d
",dp[n][m]);
}
return 0;
}