题目背景

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


题目描述

给定一个$n\times m$的矩阵,矩阵中的每个元素$a_{i,j}$为正整数。
接下来规定:
    $1.$合法的路径初始从矩阵左上角出发,每次只能向右或向下走,终点为右下角。
    $2.$路径经过的$n+m-1$个格子中的元素为$A_1,A_2...A_{(n+m-1)}$,$Aavg$为$A_i$的平均数,路径的$V$值为$(n+m-1)\times \sum \limits_{i=1}^{n+m-1}{(A_i-Advg)}^2$
求$V$值最小的合法路径,输出$V$值即可,有多组测试数据。


输入格式

第一行包含一个正整数$T$,表示数据组数。
对于每组数据:
第一行包含两个正整数$n$和$m$,表示矩阵的行数和列数。
接下来$n$行,每行$m$个正整数$a_{i,j}$,描述这个矩阵。


输出格式

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


样例

样例输入:

1
2 2
1 2
3 4

样例输出:

14


数据范围与提示

对于$30\%$的数据$n\leqslant 10$,$m\leqslant 10$。
有另外$40\%$的数据$n\leqslant 15$,$m\leqslant 15$,矩阵中的元素不大于$5$。
对于$100\%$的数据$T\leqslant 5$,$n\leqslant 30$,$m\leqslant 30$,矩阵中的元素不大于$30$。


题解

又是令人头疼的数学,而数学题就得化式子(但是你说你知道方差公式那我也没辙)。

那就来化式子:

$(n+m-1)\sum{(A_i-Aavg)}^2$
$=|(n+m-1)\times \sum({A_i}^2-2\times A_i\times Aavg+{Aavg}^2)|$
$=|(n+m-1)\times \sum{A_i}^2-(n+m-1)\times 2\times \sum (A_i\times Aavg)+(n+m-1)\times \sum{Aavg}^2|$
$=|(n+m-1)\times \sum{A_i}^2-(n+m-1)\times 2\times \frac{\sum{A_i}^2}{n+m-1}+(n+m-1)\times \frac{{Aavg}^2}{n+m-1}|$
$=|-(n+m-1)\times \sum{A_i^2}-{Aavg}^2|$
$=|{Aavg}^2-(n+m-1)\times \sum{A_i}^2|$

我们又发现矩阵中元素不大于$30$,既然它出现,必然有它的意义。

考虑从这里入手,我们现在就来考虑$DP$,定义dp[i][j][k]表示到点(i,j),和为k,平方和的最小值。

那么状态转移方程即为:$dp[i][j][k]=\min(dp[i-1][j][k-x[i][j]],dp[i][j-1][k-x[i][j]])+x[i][j]\times x[i][j]$

而我们统计答案的时候只需要找$\min(dp[n][m][i]\times (n+m-1)-i\times i)$即可。

时间复杂度:$\Theta(30\times n\times m\times (n+m))$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,m;
int Map[50][50];
int dp[50][50][2000];
int ans,maxn;
void pre_work()
{
ans=1<<30;
memset(dp,0x3f,sizeof(dp));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
pre_work();
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&Map[i][j]);
dp[1][1][Map[1][1]]=Map[1][1]*Map[1][1];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=Map[i][j];k<=(n+m-1)*30;k++)
dp[i][j][k]=min(dp[i][j][k],min(dp[i-1][j][k-Map[i][j]],dp[i][j-1][k-Map[i][j]])+Map[i][j]*Map[i][j]);
for(int i=Map[n][m];i<=(n+m-1)*30;i++)
if(dp[n][m][i]<1061109567)
ans=min(ans,dp[n][m][i]*(n+m-1)-i*i);
printf("%d\n",ans);
}
return 0;
}

rp++

最新文章

  1. 高效 Java Web 开发框架 JessMA v3.4.1
  2. Js控制Div在浏览器中的高度
  3. Can only set Cookies for the current domain
  4. 用Asp.net写自己的服务框架
  5. class org.springframework.core.type.classreading.ClassMetadataReadingVisitor has interface org.springframework.asm.ClassVisitor as super class
  6. JQuery------prevAll(),nextAll(),attr()方法的使用
  7. Backbone之旅——Model篇
  8. C#对XML进行操作(添加、修改)
  9. nodejs weixin 笔记
  10. int除以int 得到double类型值
  11. Android下NFC的简单使用
  12. Sql操作表字段
  13. Android抓包工具Fiddler抓取数据
  14. c# WinForm开发 DataGridView各种操作总结大全
  15. CSS3滤镜filter浅析
  16. Vue组件化应用构建 官网例子 Unknown custom element: &lt;todo-item&gt;
  17. C++版 - 剑指offer 面试题4: 替换空格 题解
  18. LeetCode——15. 3Sum
  19. VS开发Windows服务
  20. P2434 [SDOI2005]区间

热门文章

  1. [eclipse中使用Git插件] 008 - git操作pull、merge、stash、commit
  2. 54-python基础-python3-字符串-字符串类型及其转换
  3. Ubuntu login as root automatically
  4. Codeforces - 1191F - Tokitsukaze and Strange Rectangle - 组合数学 - 扫描线
  5. TensorFlow 安装报错的解决办法
  6. owaspbwa tickets
  7. shell根据系统当前的时间向用户输出问候信息
  8. Tutorial2
  9. 6层PCB设计技巧和步骤
  10. hadoop+spark集群搭建