C. The Sports Festival(Codeforces Round #715 (Div. 2))题解

题目链接:C. The Sports Festival
思路:区间DP,如果我们将这些数放在一个数轴上可以发现最优解的一些性质,比方说已排序后的序列[。。。。11,12,13,14],假设我们前面已经有选择过的数了,我们选择的时候一定是先选择13在选择14,因为,设没选择13之前的最小值为\(min\),那么在按顺序13,14之后对答案的贡献是\(13 - min + 14 - min\),如果不按顺序选择的话贡献是\(14 - min + 14 - min\)显然按顺序选择要优于隔空选择,那么我们就可以发现答案的性质,就是在一段连续的数轴中,最后一个选择的一定是最大值或最小值,根据这个性质,我们可以排序后按区间大小来枚举区间,因为该性质的存在,我们便知道了最优解最后一步,接下来就开始枚举最优解的最后一步,设\(f(i,j)\)表示区间\([i,j]\)上的答案,那么根据最优解最后一步的策略,该答案一定是由\(f(i+1,j) + a[j] - a[i]\)(其中a[j] - a[i]代表最后一步的选择),\(f(i,j-1) + a[j] - a[i]\),来产生的,答案取min就能得到答案。
\(Code:\)

#include<set>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(auto i=a;i<=b;++i)
#define bep(i,a,b) for(auto i=a;i>=b;--i)
#define lowbit(x) (x&(-x))
#define ch() getchar()
#define x first
#define y second
#define pc(x) putchar(x)
using namespace std;

template<typename T>void read(T&x){
static char c;static int f;
for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
static char q[65];int cnt=0;
if(x<0)pc('-'),x=-x;
q[++cnt]=x%10,x/=10;
while(x)
    q[++cnt]=x%10,x/=10;
while(cnt)pc(q[cnt--]+'0');
}

const int N = 2e3+10;
#define int long long
int n,a[N],f[N][N];
void solve(){
    read(n);
    rep(i,1,n){
        read(a[i]);
    }
    sort(a+1,a+1+n);
    rep(i,2,n){
        rep(j,1,n-i+1){
            f[j][j+i-1] = a[j+i-1] - a[j] + min(f[j][j+i-2],f[j+1][j+i-1]);
        }
    }
    write(f[1][n]);
}
signed main(){ solve(); return 0; }


posted @ 2021-04-26 21:22  xiaodangao  阅读(171)  评论(0编辑  收藏  举报