天天看点

[dp]cf gym 101485B; bzoj4426 Better Productivity(NWERC 2015 B)

@(ACM题目)[dp]

Description

ACME Inc. is reorganizing their factory, in order to maximize their productivity of useless

trinkets. The new factory design consists of p independent and identical production lines. Each production line can be assigned some number of workers.

The actual work is of course all done by machines, so the production rate of a production line is independent of the actual number of workers assigned to it. However, the workers work in shifts, and due to local safety regulations, a production line can only be active while all of its workers are present (any worker who arrives before the last person to arrive, or leaves after the first person leaves, will be spending the inactive time having a coffee break). In other words, the productivity of a production line equals the length of the timespan during which all of the workers assigned to this production line are present. Crucially, the productivity of each line must be positive (i.e., the last worker to arrive for a line must arrive strictly before the first worker for that line leaves), since otherwise the workers feel that their jobs are meaningless.

Unfortunately, due to some pesky labor laws, ACME are not allowed to fire any of their workers,

which means that each of their n workers must be assigned to some production line, even though

this may actually decrease the overall productivity of the factory.

All these rules and regulations are making a headache for ACME management. Can you

help them figure out the maximum possible total productivity (sum of productivities of the p

production lines) of their new factory?

Input

The input consists of:

- one line containing two integers n and p (1 ≤ p ≤ n ≤ 200), the number of employees

and the number of production lines;

- n lines each containing two integers a and b (0 ≤ a < b ≤ 100 000), representing a

worker that arrives at time a and leaves at time b.

You may assume that there exists at least one valid assignment of workers to production lines.

Output

Output the maximum productivity level possible for the factory

Sample Input

4 2

1 3

1 5

4 6

2 7

Sample Output

4

分析

本题题意为n个区间分为p组,求每组交的和的最大值,每组的交不能为空。

将n个区间分为两个集合:

  • A集合中的区间能覆盖n个区间中的某一个
  • B集合中的区间不能覆盖n个区间中的任何一个

    若有多个相等区间,在B中留一个。

那么A中的若和其他的区间分为一组,不会起作用,故将A中的按贪心取最大的 k 个,每个一组,在B中分剩余p−k组。

对于B,先将区间排序,dp[i][j]代表前i个区间,分为j组的最大值。只需考虑第i个区间与前面多少个分为一组,不断更新dp[i][j]即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn =  + ;
struct Data
{
    int l, r;
    bool operator < (const Data &rhs) const
    {
        if(l != rhs.l) return l < rhs.l;
        return r < rhs.r;
    }
}a[maxn], b[maxn];
int f[maxn][maxn]{}, c[maxn];
int main()
{
    int n, p;
    cin >> n >> p;
    for(int i = ; i <= n; ++ i)
        scanf("%d%d", &a[i].l, &a[i].r);
    sort(a + , a + n + );
    int cnt = , cnt2 = ;
    for(int i = ; i <= n; ++ i)
    {
        bool ck = true;
        for(int j = i + ; j <= n; ++ j)
        {
            if(a[i].l <= a[j].l && a[i].r >= a[j].r)
            {
                ck = false;
                break;
            }
        }
        int k = i - ;
        while(k >=  && a[k].l == a[i].l)
        {
            if(a[i].r > a[k].r)
            {
                ck = false;
                break;
            }
            --k;
        }
        if(ck) b[++cnt] = a[i];
        else c[++cnt2] = a[i].r - a[i].l;
    }
    f[][] = b[].r - b[].l;
    for(int i = ; i <= cnt; ++ i)
    {
        for(int j = ; j <= min(i, p); ++ j)
        {
            f[i][j] = ;
            if(f[i-][j-]) f[i][j] = f[i-][j-] + b[i].r - b[i].l;
            for(int k = i - ; k >=  && b[k].r > b[i].l; --k)
            {
                if(f[k-][j-] || k == )
                    f[i][j] = max(f[i][j], f[k-][j-] + b[k].r - b[i].l);
            }
        }
    }
    int res = f[cnt][p];
    int sum = ;
    sort(c + , c +  + cnt2);
    for(int i = cnt2, j = ; i >=  && j < p; ++ j , -- i)
    {
        sum += c[i];
        if(f[cnt][p - j])
            res = max(res, f[cnt][p-j] + sum);
    }
    cout << res << endl;
}