[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中分剩餘pk 組。

對於B,先將區間排序,dp[i][j]代表前i個區間,分爲j組的最大值。只需考慮第i個區間與前面多少個分爲一組,不斷更新dp[i][j]即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200 + 5;
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]{0}, c[maxn];
int main()
{
    int n, p;
    cin >> n >> p;
    for(int i = 1; i <= n; ++ i)
        scanf("%d%d", &a[i].l, &a[i].r);
    sort(a + 1, a + n + 1);
    int cnt = 0, cnt2 = 0;
    for(int i = 1; i <= n; ++ i)
    {
        bool ck = true;
        for(int j = i + 1; j <= n; ++ j)
        {
            if(a[i].l <= a[j].l && a[i].r >= a[j].r)
            {
                ck = false;
                break;
            }
        }
        int k = i - 1;
        while(k >= 1 && 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[1][1] = b[1].r - b[1].l;
    for(int i = 2; i <= cnt; ++ i)
    {
        for(int j = 1; j <= min(i, p); ++ j)
        {
            f[i][j] = 0;
            if(f[i-1][j-1]) f[i][j] = f[i-1][j-1] + b[i].r - b[i].l;
            for(int k = i - 1; k >= 1 && b[k].r > b[i].l; --k)
            {
                if(f[k-1][j-1] || k == 1)
                    f[i][j] = max(f[i][j], f[k-1][j-1] + b[k].r - b[i].l);
            }
        }
    }
    int res = f[cnt][p];
    int sum = 0;
    sort(c + 1, c + 1 + cnt2);
    for(int i = cnt2, j = 1; i >= 1 && j < p; ++ j , -- i)
    {
        sum += c[i];
        if(f[cnt][p - j])
            res = max(res, f[cnt][p-j] + sum);
    }
    cout << res << endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章