zoukankan      html  css  js  c++  java
  • 迎春舞会之三人组舞 vijos1061 动态规划

    描述

    n个人选出3*m人,排成m组,每组3人。

    站的队形——较矮的2个人站两侧,最高的站中间。

    从对称学角度来欣赏,左右两个人的身高越接近,则这一组的“残疾程度”越低。

    计算公式为 h=(a-b)^2 (a、b为较矮的2人的身高)
    那么问题来了。

    现在候选人有n个人,要从他们当中选出3*m个人排舞蹈,要求总体的“残疾程度”最低。

    显然是一道动态规划题目。(如果要求最大的残疾程度最小,可以二分解决)

    一道经典的线性动态规划问题,其中也利用了一个贪心的思想。
    核心:相邻最优+倒序处理
    设f[I,j]为前i个人分成j 组的最小值,其中这里的前i个人为高度前i高的人,与题目的前i个人有所不同。
    那么我们有这样的状态转移方程:
    F[I,j]=Min{f[i-1][j], f[i-2][j-1]+(a[i]-a[i-1])^2}
    说明一下:
    1.这里的f[i-1][j]表示不以较矮身份分i号人到组中
    2.f[i-2][j-1]表示以a[i], a[i-1]为两个较矮的人分成一组(即当前此人和后面的一个人一组)
    显然,在排好序后,取a,b时取相邻的总比取不相邻的要好。
    这样我们就可通过计算公式求出“残疾程度”,那么就可以了。
    而f[i-3,j-1]即默认了a[i-2], a[i-1]与a[i]形成一组,实际上残疾程度的计算与最高的人没有任何关系
    所以是f[i-2,j-1]!
    最关键的需要注意DP的方向。。
    由于题目升序排序。。故而当前第i人是最高的。。这样会发生一个很悲剧的情况:
    很有可能最后的几个二元组找不到补齐的第三人。。所以我们需要把数据倒过来处理。。
    即i循环来倒推
    这样就算最后几个人组成若干二元组。。由于n>=3*m成立所以必然可以找到对应的第三人。。
    (这段话好好理解,对dp有很大帮助)
    在有了a,b后,中间的那个人c,需要c>a,c>b,所以c的下标必在a,b前面,又因为a和b相邻
    因此循环的时候要有j<=min(m,(n-i+1)/3)。
    最后答案就是f[1][m]
    嗯表示还是要好好多明白题目意思扩展思路
    涨姿势了Orz
    我写的代码是从后往前倒序的,所以状态转移方程有所不同
    好好体会吧~

    附上AC代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    template<class T> inline void read(T &_a){
        bool f=0;int _ch=getchar();_a=0;
        while(_ch<'0' || _ch>'9'){if(_ch=='-')f=1;_ch=getchar();}
        while(_ch>='0' && _ch<='9'){_a=(_a<<1)+(_a<<3)+_ch-'0';_ch=getchar();}
        if(f)_a=-_a;
    }
    
    long long n,m,h[5001],dp[5001][1001];
    
    int main()
    {
        read(m); read(n);
        for (register int i=n;i;--i) read(h[i]);
        memset(dp,0x7f,sizeof(dp));
        for (register int i=1;i<=n;++i) dp[i][0]=0;
        for (register int i=1;i<=n;++i)
            for (register int v=1;v*3<=i&&v<=m;++v)
                dp[i][v]=min(dp[i-1][v],dp[i-2][v-1]+(h[i]-h[i-1])*(h[i]-h[i-1]));
        printf("%lld",dp[n][m]);
        return 0;
    }
  • 相关阅读:
    一步步学习SPD2010--第十一章节--处理母版页(10)--重置母版页到网站定义
    pandas转numpy并打平实例
    list和numpy互相转换
    pandas转numpy
    pandas库疑难问题---2、pandas切片操作
    pandas切片操作
    pandas中的iloc和loc用法的区别
    NumPy疑难问题---1、NumPy切片操作
    numpy切片操作
    python疑难问题---13、Python切片操作
  • 原文地址:https://www.cnblogs.com/jaywang/p/7768643.html
Copyright © 2011-2022 走看看