1. 程式人生 > >HDU6249 Alice’s Stamps(2017CCPC-Final,dp)

HDU6249 Alice’s Stamps(2017CCPC-Final,dp)

Problem Description

Alice likes to collect stamps. She is now at the post office buying some new stamps.
There are N different kinds of stamps that exist in the world; they are numbered 1 through N. However, stamps are not sold individually; they must be purchased in sets. There are M different stamp sets available; the ith set contains the stamps numbered Li through Ri. The same stamp might appear in more than one set, and it is possible that one or more stamps are not available in any of the sets.
All of the sets cost the same amount; because Alice has a limited budget, she can buy at most K different sets. What is the maximum number of different kinds of stamps that Alice can get?

Input

The input starts with one line containing one integer T, the number of test cases.T test cases follow.
Each test case begins with a line containing three integers: N, M, and K: the number of different kinds of stamps available, the number of stamp sets available, and the maximum number of stamp sets that Alice can buy.
M lines follow; the ithoftheselinesrepresentsthei^{th} stamp set and contains two integers, Li and Ri, which represent the inclusive range of the numbers of the stamps available in that set.
1≤T≤100
1≤K≤M
1≤N,M≤2000
1≤Li≤Ri≤N

Output

For each test case, output one line containing “Case #x: y”, where x is the test case number (starting from 1) and y is the maximum number of different kinds of stamp that Alice could get.

Sample Input

2
5 3 2
3 4
1 1
1 3
100 2 1
1 50
90 100

Sample Output

Case #1: 4
Case #2: 50

Hint

In sample case #1, Alice could buy the first and the third stamp sets, which contain the first four kinds
of stamp. Note that she gets two copies of stamp 3, but only the number of different kinds of stamps
matters, not the number of stamps of each kind.
In sample case #2, Alice could buy the first stamp set, which contains 50 different kinds of stamps.

思路

給你N,M,KN,M,K代表有從11NN這個區間的數字,然後接下來給出MM段區間,每段題目給出這段區間的左右端點,然後你要從中選擇KK個區間,最後使得選擇的所有段中數字種類最多,輸出最多種類,段可以重疊。

我們考慮dpdp思路:

定義:

  • dp[i][j]代表從1~i之間選擇j個區間所能達到的最大數字種類數
  • 然後我們記錄一下每一個數字向右能到達的最右端點,記為t[i]

最後可以得到狀態轉移方程:

當這一個點被某一個區間包含的時候:
	dp[t[i]][j]=max(dp[t[i]][j],dp[i-1][j-1]+當前區間覆蓋的範圍)
dp[i][j]=max(dp[i][j],dp[i-1][j])

最後求出所有的dp[i][j]的最大值即可,複雜度為O(n2)O(n^2)

程式碼

#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
const int N = 2005;
int dp[N][N]; //dp[i][j]代表前i個點選j個區間所能達到的最大數字數量
int t[N];
void solve()
{
    mem(t, 0), mem(dp, 0);
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    int x, y;
    for (int i = 0; i < m; i++)
    {
        scanf("%d%d", &x, &y);
        for (int i = x; i <= y; i++)
            t[i] = max(t[i], y); 
    }
    for (int i = 1; i <= n; i++) 
    {
        for (int j = 1; j <= k; j++)
        {
            if (t[i]) 
                dp[t[i]][j] = max(dp[i - 1][j - 1] + t[i] - (i - 1), dp[t[i]][j]);
            dp[i][j] = max(dp[i][j], dp[i - 1][j]);
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= k; j++)
            ans = max(ans, dp[i][j]);
    printf("%d\n", ans);
}
int main()
{
    freopen("in.txt", "r", stdin);
    //freopen("1.out", "w", stdout);
    int t, q = 1;
    scanf("%d", &t);
    while (t--)
    {
        printf("Case #%d: ", q++);
        solve();
    }
    return 0;
}