SDOI 2016 征途 决策单调性

本文介绍了一个关于数列分段求最小方差的问题,并通过动态规划结合决策单调性的方法给出了高效的解决方案。

题目大意:有一个数列,将其分成m段,求最小方差

先弄出n^3的dp,打出决策点,然后发现决策点是单调递增的,决策单调性搞一搞就可以了

#include<bits/stdc++.h>
#define ll long long
#define maxn 3010
using namespace std;
int n,m;
int a[maxn],sum[maxn];
double f[maxn][maxn],x;
double sqr(double x){return x*x;}
void solve(double f1[],double f2[],int l,int r,int L,int R){
    if(l>r)return;
    double t=1e20;int k;
    int mid=(l+r)>>1;
    for(int i=L;i<=R;++i){
        double p=f1[i]+sqr(sum[mid]-sum[i]-x);
        if(p<t)t=p,k=i;
    }
    f2[mid]=t;
    solve(f1,f2,l,mid-1,L,k);
    solve(f1,f2,mid+1,r,k,R);
}
int main(){
    freopen("menci_journey.in","r",stdin);
    freopen("menci_journey.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    for(int i=1;i<=n;++i)sum[i]=sum[i-1]+a[i];
    x=1.0*sum[n]/m;
    for(int i=0;i<=m;++i)
        for(int j=0;j<=n;++j)    
            f[i][j]=1e20;
    f[0][0]=0;
    for(int i=1;i<=m;++i)
        solve(f[i-1],f[i],1,n,i-1,n);
    printf("%lld\n",(ll)(f[m][n]*m+0.5));
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/117208-/p/5380275.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值