zoukankan      html  css  js  c++  java
  • 【codeforces 571B】Minimization

    time limit per test2 seconds
    memory limit per test256 megabytes
    inputstandard input
    outputstandard output
    You’ve got array A, consisting of n integers and a positive integer k. Array A is indexed by integers from 1 to n.

    You need to permute the array elements so that value

    became minimal possible. In particular, it is allowed not to change order of elements at all.
    Input
    The first line contains two integers n, k (2 ≤ n ≤ 3·105, 1 ≤ k ≤ min(5000, n - 1)).

    The second line contains n integers A[1], A[2], …, A[n] ( - 109 ≤ A[i] ≤ 109), separate by spaces — elements of the array A.

    Output
    Print the minimum possible value of the sum described in the statement.

    Examples
    input
    3 2
    1 2 4
    output
    1
    input
    5 2
    3 -5 3 -5 3
    output
    0
    input
    6 3
    4 3 4 3 2 5
    output
    3
    Note
    In the first test one of the optimal permutations is 1 4 2.

    In the second test the initial order is optimal.

    In the third test one of the optimal permutations is 2 3 4 4 3 5.

    【题目链接】:http://codeforces.com/contest/572/problem/D

    【题解】

    那个求和符所代表的内容可以写成
    |arr[1]-arr[k+1]|+|arr[2]-arr[k+2]|+……+|arr[n-k]-arr[n]|
    如果把它分成k组

    |arr[1]-arr[k+1]|+|arr[k+1]-arr[k+1+k]|+|arr[k+1+k]-arr[k+1+k+k]|+…..(其中k+1+k+…+k<=n)
    +|arr[2]-arr[k+2]|+|arr[k+2]-arr[k+2+k]|+|arr[k+2+k]-arr[k+2+k+k]|+….(其中k+2+k+…+k<=n)
    +……
    +|arr[k]-arr[k+k]|+|arr[k+k]-arr[k+k+k]|+|arr[k+k+k]-arr[k+k+k+k]|+….(其中k+k+k+…+k<=n)
    那么这k组就是没有关系的了;
    我们想让总和最小;
    必然要让绝对值里出来的结果最小;
    ->相邻的数字
    ->排序;
    则式子可以化简为
    |arr[1]-arr[k+1+k+…..+k]|+
    |arr[2]-arr[k+2+k+…k]| +
    …….
    +|arr[k]-arr[k+k+k+…k]|;
    然后每一组里面的不同数字的个数有的为n/k,而有的为n/k+1
    假设n=8,k=3
    这里写图片描述
    通过上图可以看到;
    8/3 + 1 = 3;
    且个数为3的组的个数为8%3==2
    则剩余的1组长度就为8/3==2了
    也即长度为n/k+1的有n%k组,长度为n/k的有k-n%k组
    分别设为bn和sn
    将a数组升序排
    现在相当于给你n个数字,bn个大窗口,sn个小窗口,让你把所有的数字都套住;
    设f[i][j]表示用了i个大窗口,j个小窗口获得的最小值;
    知道用了i个大窗口,j个小窗口;
    则接下来不管用什么窗口,都能直接获得要套的数字是哪些了
    因为大窗口套住t+1个数字,小窗口套住t个数字;
    且所有数字都要被套到.
    根据上面得到的化简后的式子按如下规则进行DP即可;

    f[i][j]=min(f[i][j],f[i-1][j]+a[i*(t+1)+j*t]-a[(i-1)*(t+1)+j*t+1]);
    f[i][j] = min(f[i][j],f[i][j-1]+a[i*(t+1)+j*t]-a[i*(t+1)+(j-1)*t+1]);


    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%I64d",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int MAXN = 3e5+100;
    const int MAXK = 5e3+10;
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    
    int n,k,a[MAXN],f[MAXK][MAXK];
    int bn,sn,t;
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        rep1(i,0,MAXK-1)
            rep1(j,0,MAXK-1)
                f[i][j] = 2000000000;
        rei(n);rei(k);
        rep1(i,1,n)
            rei(a[i]);
        sort(a+1,a+1+n);
        t = n/k;
        bn = n%k,sn = k-bn;
        f[0][0] = 0;
        rep1(i,0,bn)
            rep1(j,0,sn)
                {
                    if (i)
                        f[i][j] = min(f[i][j],f[i-1][j]+a[i*(t+1)+j*t]-a[(i-1)*(t+1)+j*t+1]);
                    if (j)
                        f[i][j] = min(f[i][j],f[i][j-1]+a[i*(t+1)+j*t]-a[i*(t+1)+(j-1)*t+1]);
                }
        printf("%d
    ",f[bn][sn]);
        return 0;
    }
  • 相关阅读:
    <自动化测试>之<使用unittest Python测试框架进行参数化测试>
    <自动化测试>之<unittest框架使用1>
    <自动化测试>之<selenium API 查找元素操作底层方法>
    <自动化测试>之<selenium API 用法2>
    <自动化测试>之<Selenium API 的用法1>
    <Jmeter入门不放弃>之<3.两种常见录制脚本的方法>
    <Jmeter入门不放弃>之<2.常用功能>
    <Jmeter入门不放弃>之<1.认识jmeter>
    <自动化测试>之<SeleniumIDE使用详解 >
    sql 注入get与post模式语句
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626772.html
Copyright © 2011-2022 走看看