hdu5492
Posted repulser
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu5492相关的知识,希望对你有一定的参考价值。
hdu5492
陈大哥的毒瘤题T1
题意:
差不多就是根据题意推式子,求最小方差。
解法:
首先,可以观察到,如果我们直接暴力去取平均数,很大概率会取出来小数,所以一个很直观的想法就是把平均数从式子里消去,让小数对结果不产生影响。
首先我们知道 $ ans = (n+m-1) \sum_i=1^n+m-1 (A_i - A_avg) ^ 2 $ ,根据数学知识可知 $ ans = \sum_i=1^n+m-1 (A_i^2 - 2 \times A_avg \times A_i + A_avg^2) $ , 将式子拆分后得 $ ans = (n+m-1)(A_1^2 + \cdots + A_n+m-1^2 ) + 2A_avg(n+m-1)(A_1 + \cdots + A_n+m-1) + (n + m - 1)^2 A_avg^2 $
令 $ sum = A_1 + \cdots + A_n+m-1 = \sum_i = 1^n+m-1 A_i $ , 又因为 $ A_avg = \frac\sum_i=1^n+m-1n+m-1 = \fracsumn+m-1 $
所以原式可化为 $ ans = (n+m-1)\sum_i=1^n-m+1 A_i^2 - sum $
所以现在我们只需要求出对一个给定的sum,求出最小的 $ \sum_i=1^n+m-1A_i^2 $ 即可。
所以定义状态 $ f[i][j][k] $ 表示走到 $ (i,j) $ 时,总和为k的最小代价
答案就是 $ (n+m-1)f[i][j][k] - k^2 $ 的最小值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
int a[40][40],m,n,T;
int dp[40][40][2000],rk;
inline void open_judge()
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
int main()
scanf("%d",&T);
while(T--)
rk++;
scanf("%d%d",&n,&m);
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= m ; j++)
scanf("%d",&a[i][j]);
for(int i = 0 ; i <= n ; i++)
for(int j = 0 ; j <= m ; j++)
for(int k = 0 ; k <= 1800 ; k++)
dp[i][j][k] = 1e8;
dp[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++)
if(i == 1 && j == 1) continue;
for(int k = a[i][j] ; k <= 1800 ; k++)
dp[i][j][k] = min(dp[i - 1][j][k - a[i][j]],dp[i][j - 1][k - a[i][j]]) + a[i][j] * a[i][j];
LL ans = 2147483647;
for(int k = 0 ; k <= 1800 ; k++)
LL tmp = 1ll * (n + m - 1) * dp[n][m][k] - k * k;
if(ans > tmp) ans = tmp;
printf("Case #%d: %d\n",rk,ans);
//system("pause");
return 0;
以上是关于hdu5492的主要内容,如果未能解决你的问题,请参考以下文章