题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5569
解题思路:dp[i][j]表示到达(i,j)位置时的最小值。由于目标式的特点,我们一次需要走两格,自然而然转移方程也是两次走:
dp[i][j]->dp[i+2][j],dp[i][j]->dp[i][j+2],dp[i][j]->dp[i+1][j+1]。属于简单的dp问题
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
int n,m,mat[maxn][maxn];
int dp[maxn][maxn];
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(dp,inf,sizeof(dp));
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d",&mat[i][j]);
dp[1][2] = mat[1][1] * mat[1][2];
dp[2][1] = mat[1][1] * mat[2][1];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
if(dp[i][j] == inf) continue;
if(i + 2 <= n)
dp[i+2][j] = min(dp[i+2][j],dp[i][j] + mat[i+1][j] * mat[i+2][j]);
if(j + 2 <= m)
dp[i][j+2] = min(dp[i][j+2],dp[i][j] + mat[i][j+1] * mat[i][j+2]);
if(i + 1 <= n && j + 1 <= m)
{
dp[i+1][j+1] = min(dp[i+1][j+1],dp[i][j] + mat[i][j+1] * mat[i+1][j+1]);
dp[i+1][j+1] = min(dp[i+1][j+1],dp[i][j] + mat[i+1][j] * mat[i+1][j+1]);
}
}
printf("%d\n",dp[n][m]);
}
return 0;
}