2020牛客暑期多校训练营 (第三场)E Two Matchings【排序后按照 4或6个分成1块的选择 来dp】

题目链接

这个题我搞出来一个贪心,看起来对的一批,一选是最小,然后二选也是最小,但是不能这么搞的。因为一选最小不能保证一选+二选的结果也是最小的。然后比完赛发现师兄们一开始也是这样,搞出来假贪心,还觉得正确的一批。
先对a数组sort一下,就是从a[1]到a[n]递增。
头尾取法:对于最大是必为正数的,最小是必为负数的,那么中间错开来就是说ans=2a[n]-2[1];
为了得出这个期望,应该是按照连续两个a,或者是连续4个a进行分块,然后使用这个头尾取法。
当n=16;
决策如果是2分块:16 15进行万能取法,得到2a16-2a15
决策如果是4分块:16 15 14 13进行万能取法,得到2a16-2a13
然后开始dp就行了。

我打了个假算法,然后队友一针见血说了按4 6分块。

太草了,我该反省,为什么我想不到按照4 6 分块,他想到了。
附上队友的代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<fstream>
#include<list>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps=1e-2;
const double pi=acos(-1);
ll a[200005],dp[200005];
bool cmp(ll a,ll b){
    return a>b;
}
int main(){
    int t;
    scanf("%d",&t);
    while (t--){
        int n;
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+1+n,cmp);
        if (n<=6)
        {
            printf("%lld\n",2LL*(a[1]-a[n]));
            continue;
        }
        dp[4]=a[1]-a[4];dp[6]=a[1]-a[6];dp[8]=a[1]+a[5]-a[4]-a[8];
        for (int i=10;i<=n;i+=2){
            dp[i]=min(dp[i-4]+a[i-3]-a[i],dp[i-6]+a[i-5]-a[i]);
        }
        printf("%lld\n",2*dp[n]);
    }
    return 0;
}
```c
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值