思路:区间dp
因为可以随便安排参赛人的顺序,显然我们把数组直接排序是更优的做法
定义
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]为区间
[
i
,
j
]
[i,j]
[i,j]中最小的答案,答案即为
d
p
[
1
]
[
n
]
dp[1][n]
dp[1][n]
而一个区间
[
i
,
j
]
[i,j]
[i,j]可以由区间
[
i
+
1
,
j
]
[i+1,j]
[i+1,j]添上一个
a
[
i
]
a[i]
a[i]得到或者由区间
[
i
,
j
−
1
]
[i,j-1]
[i,j−1]添上一个
a
[
j
]
a[j]
a[j]得到
由于数组是经过排序的,我们很容易得到区间的最值是
a
[
i
]
a[i]
a[i]和
a
[
j
]
a[j]
a[j]
因此转移方程为:
d
p
[
i
]
[
j
]
=
a
[
j
]
−
a
[
i
]
+
m
i
n
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
dp[i][j]=a[j]-a[i]+min(dp[i+1][j],dp[i][j-1])
dp[i][j]=a[j]−a[i]+min(dp[i+1][j],dp[i][j−1]),
d
p
[
i
]
[
i
]
=
0
dp[i][i]=0
dp[i][i]=0
区间
d
p
dp
dp一般第一层循环枚举区间长度:
for(int len=2;len<=n;len++){
for(int i=1;i<=n;i++){
int j=len+i-1;
if(j>n) break;
dp[i][j]=a[j]-a[i]+min(dp[i][j-1],dp[i+1][j]);
}
}
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef long long ll;
typedef pair<ll,ll> PII;
const int N=2e3+10,mod=1e9+7;
ll n,a[N],dp[N][N];
int main() {
IOS;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
for(int len=2;len<=n;len++){
for(int i=1;i<=n;i++){
int j=len+i-1;
if(j>n) break;
dp[i][j]=a[j]-a[i]+min(dp[i][j-1],dp[i+1][j]);
}
}
cout<<dp[1][n]<<endl;
return 0;
}