Fair Cut

作者: WilliamY | 来源:发表于2017-05-25 15:20 被阅读67次

from hackerrank
Li 和 Lu 两个人分整数,他们想分的尽量公平。公平度量为:
![](http://www.forkosh.com/mathtex.cgi? f(I) = \sum_ {i \in I}\sum_{j \in J}|a_i - a_j|)
其中![](http://www.forkosh.com/mathtex.cgi? I={i_1,i_2,...,i_k}, J = {1,...,n} \backslash I)
Li得到其中k个数,Lu得到剩下的数。

Input Format

第一行输入n (整数的数量) 和 k (Li得到的整数个数). 第二行输入n个整数,空格隔开。

Constraints
![](http://www.forkosh.com/mathtex.cgi?1 \leq k < n \leq 3000\1 \leq a_i \leq 10^9\15 % test case n \leq 20\45% test case n \leq 40)

Output Format

打印最小值的f

Sample Input 0

4 2
4 3 1 2

Sample Output 0

6

Explanation 0
![](http://www.forkosh.com/mathtex.cgi? I={2,4}, J = {1,3})
Sample Input 1

4 1
3 3 3 1

Sample Output 1

2

Explanation 1
![](http://www.forkosh.com/mathtex.cgi? I={1}, J = {2,3,4})

动规解

首先将数字排序,而后做一个背包问题:
![](http://www.forkosh.com/mathtex.cgi? dp[\alpha][\beta][\gamma] = min. \sum_ {i \in I}\sum_{j \in J}|a_i - a_j|;\ I=\beta,I \subset {1,...,\alpha};\J = {1,...,\alpha}\backslash I;\\sum_{i \in I} a_i = \gamma.)
每一步都有两个选择,将数字分给Li和Lu.
第一种情况,
第二种情况,
解就是:


be equal to (every number in is less or equal than , so we know how to resolve absolute value). In the second case we will get to the state and new function will be . The answer for the problem is .
This approach gives us pseudo-polynomial solution but it's not enough for the problem. In the first approach we noticed that information about sum of Li's numbers is enough to recalculate the function. Also it's clear that we express function for the new state as linear combination of function for the old state and sum of Li's numbers in the old state. This thought pushes us to extend dp state in the another way: minimal possible . To calculate we should consider two cases: if the last integer is Li's and if it's Lu's. In the first case intended value is
(similarly to the first approach). In the second case it is . Answer for the problem is . To obtain solution we should notice that with fixed and we have only one interesting (because in the end we are interested only in the state and changing of depends on changing of ).
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
#define mp make_pair
#define pb push_back
#define sz(x) ((int) (x).size())


#define X first
#define Y second

const int maxn = 3005;
ll a[maxn];
ll dp[2][maxn]; // minimal possible (unfairness - coef * (sum of Li's integers))

int main()
{
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    sort(a, a + n);
    for (int i = 0; i <= 1; i++)
       for (int j = 0; j <= k; j++)

              dp[i][j] = (i==0 && j==0?0ll:(ll)1e18);
    ll psum = 0ll;
    int coef;
    for (int i = 1; i <= n; i++)
    {
       for (int j = 0; j <= k; j++)
         {
            coef = (k-j)*2 - (n-i);
            dp[i&1][j] = min(dp[(i-1)&1][j] + (ll)j * a[i-1],  //Lu's
              (j>0 ? dp[(i-1)&1][j-1] - psum + (ll)coef * a[i-1] + (ll)(i-j) * a[i-1] : (ll)1e18));

         }
       psum += a[i-1];
    }
    cout << dp[n&1][k] << endl;
    return 0;
}

贪心解【from Discussion

根据物理的“平衡定律law of equilibium”, 这道题相当于求一个电势平衡。
The optimal cut is independent of the numbers, but only depends on their order. For example, if there are N=10 numbers to cut, and one person gets K=3 numbers, the best cut will be 0001010100, which means we first sort the 10 numbers in ascending order A[1]<=A[2]<=...<=A[10], and give the 0s to one person and the 1s to another. The strategy is to place the 01-string repetition (the "010101" in the example) as close to the middle of the whole string as possible. If K*2>N, redefine K to be N-K (switching the 0s and 1s). The intuition behind this greedy strategy comes from physics. The unfairness is like an interaction potential to be minimized. The 0s and 1s attract each other and form an ionic crystal in the middle of a positive charge background.

n, k = map(int, raw_input().split(' '))
l = map(int, raw_input().split(' '))
l.sort()
if k > n / 2:
    k = n - k
t = (n-2*k) / 2
if (n - 2*k)%2 == 0:
    dig_str = '0'* t + '01' * k + '0' * t
else:
    dig_str = '0'* (t + 1) + '10' * k + '0' * t
I = [i for i in range(n) if dig_str[i] == '1']
J = [i for i in range(n) if dig_str[i] == '0']
print sum([abs(l[i]-l[j]) for i in I for j in J])

相关文章

  • Fair Cut

    from hackerrankLi 和 Lu 两个人分整数,他们想分的尽量公平。公平度量为:![](http://...

  • Destiny

    Do you think destiny is fair? Or Unfair? Fair for all of ...

  • cut and thrust,看这个短语的构造,一定是大架势

    ​cut 对应的习语不少,例如:cut sb some slack,cut to the chase 和 cut ...

  • 记一首喜欢的英国民歌

    《Scarborough Fair》 主歌:Are you going to Scarborough Fair?你...

  • Inspirational College Students

    The world is not fair, the world is very fair, you get, i...

  • 无标题文章

    Vanity Fair—Vanity Fair!Here was a man, who could not spe...

  • 不公平

    it's not fair~ what is not fair?why~ i've been here four ...

  • Fair

    存档。 Fair Candy 想想那也是很久以前的事了。 地下城市桑古奈姆的空气中好像永远都弥漫着某种令人感...

  • fair

    夜晚正做着好梦,突然被冻醒。赶忙下床关电扇。怕惊醒孩子,没有敢开灯,摸黑关罢电扇返回时心里迷迷茫茫的想:哎呀,不要...

  • 英文版“诗经”---斯卡布罗集市

    Scarborough Fair 斯卡布罗集市 Are you going to Scarborough Fair...

网友评论

      本文标题:Fair Cut

      本文链接:https://www.haomeiwen.com/subject/gfaaxxtx.html