Time Limit: 10000/5000 MS (Java/Others)
Memory Limit: 999999/400000 K (Java/Others)
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
T
T be a set of integers. Let the
M
I
N
MIN
MIN be the minimum integer in
T
T
T and
M
A
X
MAX
MAX be the maximum, then the cost of set T if defined as
(
M
A
X
–
M
I
N
)
2
(MAX – MIN)^2
(MAX–MIN)2. Now given an integer set
S
S
S, we want to find out
M
M
M subsets
S
1
,
S
2
,
…
,
S
M
S_1, S_2, …, S_M
S1,S2,…,SM of
S
S
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
)
N (≤ 10,000)
N(≤10,000) and
M
(
≤
5
,
000
)
M (≤ 5,000)
M(≤5,000).
N
N
N is the number of elements in
S
S
S (may be duplicated).
M
M
M is the number of subsets that we want to get. In the next line, there will be
N
N
N integers giving set
S
S
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.
Source
2010 ACM-ICPC Multi-University Training Contest(5)——Host by BJTU
题意:
将
n
n
n个数字分成
m
m
m份每份的代价是
(
最
大
数
−
最
小
数
)
2
(最大数-最小数)^2
(最大数−最小数)2,求最小代价
题解:
我们可以贪心的知道如果把排序之后连续的一段数字分成一份,那么将会是最优的。
那么之后我们就可以设
f
[
i
]
[
j
]
f[i][j]
f[i][j]是前
i
i
i个数字分成
j
j
j份之后最小代价是多少。
得出DP方程
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
]
[
j
]
,
f
[
k
]
[
j
]
+
(
a
[
i
]
−
a
[
k
+
1
]
)
∗
(
a
[
i
]
−
a
[
k
+
1
]
)
)
f[i][j]=min(f[i][j],f[k][j]+(a[i]-a[k+1])*(a[i]-a[k+1]))
f[i][j]=min(f[i][j],f[k][j]+(a[i]−a[k+1])∗(a[i]−a[k+1]))
然后用四边形不等式优化之后再滚动数组,就可以过了。
#include<bits/stdc++.h>
#define LiangJiaJun main
#define INF 19991227000LL
#define ll long long
using namespace std;
ll SQR(ll A){return A*A;}
ll f[10004][2];
int s[10004][5004];
int n,m;
int a[10004];
int w33ha(int CASE){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+n+1);
memset(f,0,sizeof(f));
for(int i=0;i<=n+1;i++)
for(int j=0;j<=m+1;j++)
s[i][j]=0;
for(int i=1;i<=n;i++){
f[i][1]=SQR(1LL*(a[i]-a[1]));
s[i][1]=0;
s[i][i]=i;
}
for(int j=2;j<=m;j++){
s[n+1][j]=n;
for(int i=n;i>=j;i--){
f[i][j&1]=INF;
for(int k=s[i][j-1];k<=s[i+1][j];k++){
if(f[i][j&1]>f[k][(j-1)&1]+SQR(1LL*(a[i]-a[k+1]))){
f[i][j&1]=f[k][(j-1)&1]+SQR(1LL*(a[i]-a[k+1]));
s[i][j]=k;
}
}
}
}
printf("Case %d: %lld\n",CASE,f[n][m&1]);
return 0;
}
int LiangJiaJun(){
int T;scanf("%d",&T);
for(int i=1;i<=T;i++)w33ha(i);
return 0;
}