施魔法

施魔法

http://www.nowcoder.com/questionTerminal/be328380264f49f59936d69f023cac6d

施魔法
https://ac.nowcoder.com/acm/contest/3003/H
图片说明

先从小到大排序,极差转换为--连续一段数尾部和开头的差值
DP[i]就是前i个元素以i为尾划分段的最小值
i可以是 作为前一段的新尾,DP[i]=DP[i-1]-A[i-1]+A[i]
也可是新开一段k,作为段尾 DP[i]=DP[i-k]-A[i-k+1]+A[i] (A[i-k+1]是头,A[i]是尾)
则动态转移方程为 DP[i]=min(DP[i-1]-A[i-1]+A[i],DP[i-k]-A[i-k+1]+A[i])
需要注意的是1~k必须组成一个段,所以循环从 k+1 开始
注意:能够新开一段最早是从k+1为头开始,一开始对DP数组进行初始化操作使其为INF,使得其进行
操作时,在k+1之前不能取其为头
另需记得:DP[k]=A[k]-A[1]

#pragma warning (disable :4996)
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 3e5 + 10;

int n, k;
int M[N];
int DP[N];
int main() {
    scanf("%d %d", &n,&k);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &M[i]);
    }
    sort(M+1, M + n+1);
    for (int i = 1; i <= n; i++)
        DP[i] = INF;
    DP[k] = M[k] - M[1];
    for (int i = k+1; i <= n; i++) {
        DP[i] = min(DP[i - 1] - M[i - 1] + M[i], DP[i - k ] - M[i - k + 1] + M[i]);
    }
    cout << DP[n] << endl;

}
全部评论

相关推荐

点赞 评论 收藏
转发
4 收藏 评论
分享
牛客网
牛客企业服务