nodgd 好路线 noip 2015 模拟赛 T3

这里写图片描述

这里写图片描述

解析:

对于此题,我们选择从方差的表达式入手,我们已知k是经过的点的数目,而到达重点是经过了(n+m-1)个点,令N=(n+m-1),此时x(即海拔)的平均值为(x1+x2+x3+…+xN)/N,(为了方便,用x_来代替x的平均值),σ^2=((x1-x_)^2+(x2-x_)^2+…+(xN-x_)^2)/N,
而最终答案(n+m-1)^2*σ^2=N^2*σ^2,将原式带入得到答案 ans=N*(x1^2+…+xN^2)-(x1+…+xN)^2。
具体过程如下:
N^2*σ^2
=N*((x1-x_)^2+…+(xN-x_)^2)
=N*((x1^2-2*x1*x_)^2+…+(xN^2-2*xN*x_+x_^2))
=N*((x1^2+…+xN^2)-2*x_*(x1+…+xN)+N*(x_^2))
然后再将x_=(x1+…+xN)/N带入,即可得到ans表达式。
易得,在某点的ans为 当前经过的点的数目乘以那些点的高度的平方的和 再减去它们的高度的和的平方。(有点儿绕)
因此我们可以设定一个DP状态f[i][j][k],k表示到达点(i,j)时,经过的点的高度的和(只是和,没有平方!)(包括(i,j)),f[i][j][k]的值则表示它们的高度的平方和。
因此动态转移方程为:
f[i][j][k]=min(f[i-1][j][k-h[i][j]],f[i][j-1][k-h[i][j]])+h[i][j]^2.
讲到这就差不多了,贴代码!!

#include<stdio.h>
#include<string.h> 
int f[51][51][5100];
int h[51][51];
int min(int x,int y){
    return x>=y?y:x;
}
int pf(int x){
    return x*x;
}
int main(){
    int n,m;
    int i,j,k;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
            scanf("%d",&h[i][j]);
    memset(f,-1,sizeof(f));
    f[1][0][0]=f[0][1][0]=0;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            int s=(i+j-1)*50;   //高度和的上限
            for(k=h[i][j];k<=s;k++){  //只是和,没有平方
                if(f[i-1][j][k-h[i][j]]!=-1&&f[i][j-1][k-h[i][j]]!=-1)   //左边和上边的点都可以更新当前的点
                    f[i][j][k]=min(f[i-1][j][k-h[i][j]],f[i][j-1][k-h[i][j]])+pf(h[i][j]);
                else if(f[i-1][j][k-h[i][j]]!=-1)  //只有左边的点可以
                    f[i][j][k]=f[i-1][j][k-h[i][j]]+pf(h[i][j]);
                else if(f[i][j-1][k-h[i][j]]!=-1)  //只有上边的点可以
                    f[i][j][k]=f[i][j-1][k-h[i][j]]+pf(h[i][j]);
            }
        }
    }
    int ans=1e9+9;
    for(i=0;i<=(n+m-1)*50;i++)
        if(f[n][m][i]!=-1)
            ans=min(ans,(n+m-1)*f[n][m][i]-i*i);
    printf("%d",ans);  //直接代入公式 N*(x1^2+...+xN^2)-(x1+...+xN)^2
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值