• 题解 【打饭】


    【题目描述】

    (n) 个小朋友来食堂吃饭,他们排成长度为 (n) 的一个队伍。

    小朋友看到别的小朋友比自己菜好会不高兴,两个小朋友i和j能互相看到对方的菜当且仅当 (operatorname{abs}(i-j)==k),产生的不高兴值是 (operatorname{abs}(a_i-a_j))(operatorname{abs}) 是取绝对值符号,(a_i) 表示第i位小朋友菜丰盛的程度,换言之,如果菜的丰盛值按顺序排列是序列 (A),那么产生的不高兴值为

    [sumlimits_{i=1}^{n-k} abs(a[i]-a[i+k]) ]

    如果小朋友产生的不高兴值和太大他们会哭,你现在有 (n) 盘菜,请你合理安排上菜顺序,使得产生不高兴值的和最小,输出这个值。

    【输入格式】

    第一行输入两个正整数 (n)(k)

    第二行 (n) 个整数,表示第 (i) 盘菜的丰盛值 (a_i)

    【输出格式】

    一个数表示最小的不高兴值和

    【样例输入输出】

    【输入 #1】
    3 2
    1 2 4
    
    【输出 #1】
    1
    
    【输入 #2】
    5 2 
    1 3 1 3 1
    
    【输出 #2】
    0
    
    【输入 #3】
    6 3 
    4 3 4 3 2 5
    
    【输出 #3】
    3
    

    【数据范围与提示】

    对于 (30\%) 的数据,满足 $n leq 10 $

    对于 (50\%) 的数据,满足 $n,k leq 5000 $

    对于另外 (30\%) 的数据,满足 (n)(k) 的倍数

    对于 (100\%) 的数据,满足 (n leq 300000,k leq min(n-1,5000), -10^9 leq a_i leq 10^9)

    时间限制:(1 ext {s})

    空间限制:(512 ext {MB})


    题目可以转换为:在一个排好序的数列中,求几个区间相邻的每个数的差

    因为每相邻 (k) 个求一次差,所以每个区间的长度只可能是 (n/k)(n/k+1)

    (f_{i,j}) 表示取 (i) 个长度为 (n/k) 的区间和 (j) 个长度为 (n/k+1) 的区间的不高兴值的和最小值是多少

    然后我们可以得到转移方程

    (f[i+1][j]=min(f[i+1][j],f[i][j]+a[(i+1)*(n/k+1)+j*(n/k)]-a[i*(n/k+1)+j*(n/k)+1]))

    (f[i][j+1]=min(f[i][j+1],f[i][j]+a[i*(n/k+1)+(j+1)*(n/k)]-a[i*(n/k+1)+j*(n/k)+1]))

    然后就好了αωα

    #include<bits/stdc++.h>
    #define rint register long long
    #define int long long
    using namespace std;
    inline int read(){
        int s=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
        while(c>='0'&&c<='9')s=(s<<1)+(s<<3)+c-48,c=getchar();
        return f?s:-s;
    }
    int n,k,a[300010],now,ans;
    int f[5010][5010];
    signed main(){
        freopen("rice.in","r",stdin);
        freopen("rice.out","w",stdout);
        n=read(); k=read();
        for(rint i=1;i<=n;++i) a[i]=read();
        sort(a+1,a+1+n);
        memset(f,0x3f,sizeof f);
        f[0][0]=0;
        int m_k1=n%k,m_k2=k-n%k;
        for(int i=0;i<=m_k1;++i)
            for(int j=0;j<=m_k2;++j){
            if(i!=m_k1) f[i+1][j]=min(f[i+1][j],f[i][j]+a[(i+1)*(n/k+1)+j*(n/k)]-a[i*(n/k+1)+j*(n/k)+1]);
            if(j!=m_k2) f[i][j+1]=min(f[i][j+1],f[i][j]+a[i*(n/k+1)+(j+1)*(n/k)]-a[i*(n/k+1)+j*(n/k)+1]);
        }
        printf("%lld",f[m_k1][m_k2]);
        return 0;
    }
    
  • 相关阅读:
    rabbitmq消息路由
    rabbitmq消息消费
    python中的正则匹配
    Spectral Grouping Using Nystrom Method
    基于WKPCA的多路谱聚类算法
    基于加权KPCA的谱聚类算法
    单词拆分
    完全平方数
    零钱兑换
    组合总数
  • 原文地址:https://www.cnblogs.com/LCGUO/p/12591939.html
Copyright © 2020-2023  润新知