zoukankan      html  css  js  c++  java
  • 8597 石子划分问题 dpdp,只考虑第一次即可

    8597 石子划分问题

    时间限制:500MS  内存限制:1000K
    提交次数:155 通过次数:53

    题型: 编程题   语言: G++;GCC;VC

     

    Description

    给定n个石子,其重量分别为a1,a2,a3,...,an。
    要求将其划分为m份,每一份的划分费用定义为这份石子中最大重量与最小重量差的平方。
    总划分费用为m份划分费用之和。
    
    现在对于给定的n个石子,求一种划分方案,使得总划分费用最小。
    




    输入格式

    第一行两个正整数n和m,接下来一行有n个正整数,表示一个石子的重量ai。(1≤n, m, ai≤1000)



    输出格式

    计算输出最小总划分费用。
    
    注意:若一份只有一个石子,那么,这份石子中最大重量与最小重量的差的平方为0。



     

    输入样例

    4 2
    4 7 10 1



     

    输出样例

    18



     

    提示

    1,先将石子重量从小到大排序(从大到小也可以).
    2,假设f(n,m)表示:n个石头分成m份的最小费用. 特别的,有f(1,1)=0; f(n,1)=(an - a1)^2
    那么,除去最后一份石头的若干个,前面m-1份必定也是最优的分法.
    若最后一堆1个石头, f(n,m) = f(n-1,m-1)+0^2
    若最后一堆2个石头, f(n,m) = f(n-2,m-1)+(an - an-1)^2
    若最后一堆3个石头, f(n,m) = f(n-3,m-1)+(an - an-2)^2
    ......
    最后一堆最多只能有n-m+1个石头,因为当最后一堆为n-m+1时,前面m-1堆已经是一个一份了.
    因此, f(n,m) = Min{ f(n-1,m-1)+0^2,  f(n-2,m-1)+(an - an-1)^2,  ...}
    
    例如:
    n=5, m=2
    a[1..5] = 1 3 4 8 9
    f(5,2)=Min{ f(4,1)+0; f(3,1)+1; f(2,1)+5^2 }=Min{49,10,29}=10
    这5个石头分2堆的最优分法:(1 3 4)(8 9)
    
    



    这题需要记录,做的时候居然又忘记了。

    首先贪心,排序后,相邻的排在一堆是必然的。

    然后每次只考虑最后一堆即可是吧,其他的递归处理。

    所以,设dp[i][j]表示前i个数字,分成j堆的最小值。

    那么,考虑最后一堆,肯定是min(dp[1...i-1][j-1]   +   pow(a[n] - a[n - i + 1], 2));

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    const int maxn = 1e3 + 20;
    int dp[maxn][maxn];
    int a[maxn];
    int dfs(int n, int m) {
        if (m == 1) return (a[n] - a[1]) * (a[n] - a[1]);
        if (n == m) return 0;
        if (dp[n][m]) return dp[n][m];
        int ans = 1e9;
        for (int i = 1; i <= n - m + 1; ++i) {
            ans = min(ans, dfs(n - i, m - 1) + (a[n] - a[n - i + 1]) * (a[n] - a[n - i + 1]));
        }
        return dp[n][m] = ans;
    }
    
    void work() {
        int n, m;
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) cin >> a[i];
        sort(a + 1, a + 1 + n);
        cout << dfs(n, m) << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code

     

    作者

     zhengchan

  • 相关阅读:
    解决哈希(HASH)冲突的主要方法
    破解
    打工
    [JSOI2007]麻将
    [JSOI2007]建筑抢修
    [HAOI2007]上升序列
    [HAOI2007]覆盖问题
    [CQOI2017]小Q的棋盘
    [HEOI2015]兔子与樱花
    [HEOI2015]定价
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/8262163.html
Copyright © 2011-2022 走看看