hdu3480-Division

Division

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 999999/400000 K (Java/Others)
Total Submission(s): 5640    Accepted Submission(s): 2235


Problem Description
Little D is really interested in the theorem of sets recently. There’s a problem that confused him a long time.  
Let T be a set of integers. Let the MIN be the minimum integer in T and MAX be the maximum, then the cost of set T if defined as (MAX – MIN)^2. Now given an integer set S, we want to find out M subsets S1, S2, …, SM of S, such that



and the total cost of each subset is minimal.
 

Input
The input contains multiple test cases.
In the first line of the input there’s an integer T which is the number of test cases. Then the description of T test cases will be given. 
For any test case, the first line contains two integers N (≤ 10,000) and M (≤ 5,000). N is the number of elements in S (may be duplicated). M is the number of subsets that we want to get. In the next line, there will be N integers giving set S.

 

Output
For each test case, output one line containing exactly one integer, the minimal total cost. Take a look at the sample output for format.

 

Sample Input
 
  
2 3 2 1 2 4 4 2 4 7 10 1
 

Sample Output
 
  
Case 1: 1 Case 2: 18
Hint
The answer will fit into a 32-bit signed integer.
 
 

题意:开始有一个集合S,里面有n个数字,现在把该集合拆成m个子集和,并要求子集和求并集后等于S,问总策略之和最小为多少?

总策略等于各个集合的最大值减最小值之差的平方!

题解:首先很明显要对数组排序。我使用升序排序。

设dp[i][j]为拆成i个集合后覆盖前j个元素的最小和,则dp[i][j] = min{dp[i - 1][k] + cost[k + 1][j]};

cost[k + 1][j] = (a[j] - a[k + 1])^2

使用四边形优化即可

AC代码

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
typedef unsigned int ll;
 
using namespace std;

const ll maxn = 1e4 + 10, inf = 0xFFFFFFFF;
ll a[maxn], dp[2][maxn], s[2][maxn];

int main(){
	ll t, n, m;
	while(scanf("%u", &t) != EOF){
		ll ca = 1;
		while(t--){
			scanf("%u %u", &n, &m);
			for(ll i = 1; i <= n; i++)
				scanf("%u", &a[i]);
			sort(a + 1, a + 1 + n);
			for(ll j = 1; j <= n; j++){
				s[1][j] = 1;
				dp[1][j] = (a[j] - a[1]) * (a[j] - a[1]);
			}
			for(ll i = 2; i <= m; i++){
				s[i & 1][n + 1] = n - 1;
				for(ll j = n; j >= i; j--){
					if(i == j)
						dp[i & 1][j] = 0;
					else
						dp[i & 1][j] = inf;
					for(ll k = s[(i + 1) & 1][j]; k <= s[i & 1][j + 1]; k++){
						if(dp[i & 1][j] > dp[(i + 1) & 1][k] + (a[j] - a[k + 1]) * (a[j] - a[k + 1])){
							dp[i & 1][j] = dp[(i + 1) & 1][k] + (a[j] - a[k + 1]) * (a[j] - a[k + 1]);
							s[i & 1][j] = k;
						}
					}
				}
			}
			printf("Case %u: %u\n", ca++, dp[m & 1][n]);
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_37064135/article/details/80450833
今日推荐