小奇的矩阵 DP

小奇的矩阵

【题目背景】

小奇总是在数学课上思考奇怪的问题。

【问题描述】

给定一个n*m的矩阵,矩阵中的每个元素aij为正整数。

接下来规定

1.合法的路径初始从矩阵左上角出发,每次只能向右或向下走,终点为右下角。

2.路径经过的n+m-1个格子中的元素为A1,A2…A(n+m-1),Aavg为Ai的平均数,路径的V值为(n+m-1)*∑(Ai-Aavg) ^2

(1<=i<=n+m-1)

求V值最小的合法路径,输出V值即可,有多组测试数据。

输入格式

第一行包含一个正整数T,表示数据组数。

对于每组数据:

第一行包含两个正整数n和m,表示矩阵的行数和列数。
接下来n行,每行m个正整数aij,描述这个矩阵。

输出格式

对于每次询问,输出一行一个整数表示要求的结果

样例输入

1
2 2
1 2
3 4

样例输出

14

数据规模

对于30%的数据 n<=10,m<=10

有另外40%的数据 n<=15 m<=15,矩阵中的元素不大于5

对于100%的数据 T<=5,n<=30,m<=30,矩阵中的元素不大于30


看到方差的形式也不能打出GG。

首先容易看出来是一个DP,因为有明显的阶段性,而且很容易想到有两维应该用来记录位置。但是应该记录什么呢?是否应该加维数呢?

留给我们的突破口就只有答案的这个式子了,所以其实本题比较好想。对于题面里的形式显然是难以处理的,考虑对式子变形。

Ans=(n+m1)(AiAvg)2
       =(n+m1)(A2i2AvgAi+Avg2)
       =(n+m1)(A21+A22++A2n+m1)2Avg(n+m1)(A1+A2+An+m1)+(n+m1)2Avg2

不妨设 Sum=A1+A2+A3++An+m1 ,那么根据平均数的定义有 Avg(n+m1)=Sum ,代入上式化简得

Ans=(n+m1)(A21+A22++A2n+m1)2Sum2+Sum2
       =(n+m1)(A21+A22++A2n+m1)Sum2

所以现在我们只需要求出对一个给定的 Sum ,求出对应最小的 (A21+A22++A2n+m1) 即可。

所以定义状态 f[i][j][k] 表示当前走到 (i,j) ,当前得到的总和为 k 时的最小(A21+A22++A2i+j1)。状态转移方程:

f[i][j][k]=min(f[i1][j][kAij]+f[i][j1][kAij])+A2ij

要得到最终答案,枚举 (n+m1)f[n][m][k]k2 的最小值即可。


#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;

int N,M,Map[35][35],f[35][35][1805];
long long Ans,Tmp;

int main()
{
    int i,j,k,T;

    scanf("%d",&T);

    while(T--)
    {
        scanf("%d%d",&N,&M);

        for(i=1;i<=N;i++)
        for(j=1;j<=M;j++)
        scanf("%d",&Map[i][j]);

        for(i=0;i<=N;i++)
        for(j=0;j<=M;j++)
        for(k=0;k<=1770;k++)f[i][j][k]=1e8;

        f[1][1][Map[1][1]]=Map[1][1]*Map[1][1];

        for(i=1;i<=N;i++)
        for(j=1;j<=M;j++)
        {
            if(i==1&&j==1)continue;
            for(k=Map[i][j];k<=1770;k++)
            f[i][j][k]=min(f[i-1][j][k-Map[i][j]],f[i][j-1][k-Map[i][j]])+Map[i][j]*Map[i][j];
        }

        Ans=1e9;
        for(k=0;k<=1770;k++)
        {
            Tmp=1ll*(N+M-1)*f[N][M][k]-k*k;
            if(Ans>Tmp)Ans=Tmp;
        }

        printf("%lld\n",Ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值