Find a path
题目链接
题目大意
给你一个n*m的矩阵,让你找一条路径从左上角到达右下角,要求方差最大
(N+M−1)∑i=1N+M−1(Ai−Aavg)2
题解
经过变换,我们可以把题目中所给的式子变成这样:
(N+M−1)∑i=1N+M−1A2i−SUM2
其中SUM是路径上所有Ai的和。
通过这个式子我们可以看到我们需要维护 A2i 和SUM的值:
我们用Di,j,k表示到(i,j)时和为k的最大平方和,换句话说:Di,j,k=∑i=1i+j−1A2i (∑i=1i+j−1Ai=k)
最后取最大,算出结果就行了。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define LL long long
using namespace std;
int T,n,m;
LL a[35][35],d[35][35][2005];
int main()
{
int Case=1;
scanf("%d",&T);
while (T--)
{
memset(a,0,sizeof(a));
memset(d,-1,sizeof(d));
scanf("%d%d",&n,&m);
LL t=n+m-1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) scanf("%I64d",&a[i][j]);
//DP
d[1][1][a[1][1]]=a[1][1]*a[1][1];
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int k=a[i][j];k<=2000;k++)
{
if (i==1 && j==1) continue;
if (d[i-1][j][k-a[i][j]]!=-1)
d[i][j][k]=d[i-1][j][k-a[i][j]]+a[i][j]*a[i][j];
if (d[i][j-1][k-a[i][j]]!=-1 && d[i][j][k]!=-1)
d[i][j][k]=min(d[i][j-1][k-a[i][j]]+a[i][j]*a[i][j],d[i][j][k]);
else if (d[i][j-1][k-a[i][j]]!=-1 && d[i][j][k]==-1)
d[i][j][k]=d[i][j-1][k-a[i][j]]+a[i][j]*a[i][j];
}
LL ans=0x7fffffffffffffff;
for (int i=0;i<=2000;i++)
{
if (d[n][m][i]!=-1 && ans>d[n][m][i]*t-(i*i) ) ans=t*d[n][m][i]-(i*i);
}
printf("Case #%d: %I64d\n",Case++,ans);
}
return 0;
}