解题思路:dp[i][j]表示点(i,j)的最小贡献
分成三类来计算
#include<stdio.h>
#include<iostream>
#include<string.h>
#define MAX 1e9+5
using namespace std;
int mp[1005][1005];
int dp[1005][1005];
int min(int a,int b)
{
return a>b?b:a;
}
int main()
{
int n,m;
int i,j,k;
while (~scanf ("%d%d",&n,&m))
{
for (i=1; i<=n; i++)
{
for (j=1; j<=m; j++)
dp[i][j]=0;
}
for (i=1; i<=n; i++)
for (j=1; j<=m; j++)
scanf ("%d",&mp[i][j]);
for (i=1; i<=n; i++)
{
for (j=1; j<=m; j++)
{
if ((i+j)%2)//只需要计算奇数的
{
if (i>2 &&j>2)
{
int a,b,c,d;
a=dp[i][j-2]+mp[i][j-1]*mp[i][j];
b=dp[i-1][j-1]+mp[i][j-1]*mp[i][j];
c=dp[i-1][j-1]+mp[i-1][j]*mp[i][j];
d=dp[i-2][j]+mp[i-1][j]*mp[i][j];
dp[i][j]+=min(min(a,b),min(c,d));
}
if (i==2 && j>2)
{
int a,b,c;
a=dp[i-1][j-1]+mp[i-1][j]*mp[i][j];
b=dp[i-1][j-1]+mp[i][j-1]*mp[i][j];
c=dp[i][j-2]+mp[i][j-1]*mp[i][j];
dp[i][j]=min(min(a,b),c);
}
if (j==2 && i>2)
{
int a,b,c;
a=dp[i-1][j-1]+mp[i-1][j]*mp[i][j];
b=dp[i-1][j-1]+mp[i][j-1]*mp[i][j];
c=dp[i-2][j]+mp[i-1][j]*mp[i][j];
dp[i][j]=min(min(a,b),c);
}
if (i==1 && j>1) dp[i][j]=dp[1][j-2]+mp[1][j-1]*mp[1][j];//在最外侧的点
if (j==1 && i>1) dp[i][j]=dp[i-2][j]+mp[i-1][1]*mp[i][1];//在最外侧的点
}
}
}
printf("%d\n",dp[n][m]);
}
return 0;
}