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

原文地址:https://www.cnblogs.com/liuweimingcprogram/p/8262163.html