SDUT 2021 Autumn Team Contest 36th G - Alice’s Stamps(补)

队友做出的这个题,赛后补的=、=

G - Alice’s Stamps (一般DP)

题目大意 :给你m个区间,选k个,求k个区间并集
1≤T≤100
1≤K≤M
1≤N,M≤2000
1≤Li≤ Ri ≤N
输出 :满足题意的最大的区间并

分析:

纯看数据范围很像是一般的背包dp,但是和常规背包不同,更像是一般的线性dp。同时一般的背包思维也不好想这个题。但我们用线性思维,先找出当前点在所有包含区间中的最左边界,(队友用当前点的最右边界写的也可过)
然后我们dp[i][j]表示为从左到j的区间内选i个区间的最大答案.
状态取 max.
(b[i]就是当前点的最小左区间在哪)然后能得dp方程 :

dp[i][j + 1] = max(max(dp[i][j + 1], dp[i][j]), dp[i - 1][b[j]] + j - b[j] + 1);

C++代码

/*made in dirt & sand */
#include <bits/stdc++.h>

#include <deque>
#define bug(a) cout << a << endl
#define mem(a, b) memset(a, b, sizeof a)
#define bug2(a, b) cout << a << ' ' << b << endl
#define bug3(a, b, c) cout << a << ' ' << b << ' ' << c << endl
#define lowbit(x) (x & -x)
#define pb push_back
#define int long long
#define x first
#define y second
#define pii pair<int, int>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10, M = 1e7 + 10;
const int inf = 1e-6;
int i, j, k, n, m, l, x, y, t, ge, hao, ans[N], b[N], d[N];
vector<int> mp[N];
bool p[N];
struct ss
{
    int x, y;
} a[N];
int dp[2010][2010];
bool cmp(ss x, ss y)
{
    return x.x < y.x;
}
signed main()
{
    // freopen("black.in","r",stdin);
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    int ans = 0;
    int T;
    cin >> T;
    for (int ii = 1; ii <= T; ii++)
    {
        cin >> n >> m >> k;
        
        for (i = 1; i <= n; i++)
            b[i] = n + 10;
        for (i = 0; i < m; i++)
        {
            cin >> a[i].x >> a[i].y;
        }
        sort(a, a + m, cmp);
        int l = 1;
        for (i = 0; i < m; i++)
        {
            for (; l <= a[i].y; l++)
            {
                b[l] = a[i].x;
            }
        }
        for (j = 1; j <= n; j++)
        {
            for (i = 1; i <= k; i++)
            {
                dp[i][j + 1] = max(max(dp[i][j + 1], dp[i][j]), dp[i - 1][b[j]] + j - b[j] + 1);
            }
            ans = dp[k][j+1];
        }
            
        for(int nn = 0 ; nn <= m + 10 ; nn ++ ){
            for(int mm = 0 ; mm <= n+11 ; mm ++ ){
                dp[nn][mm] = 0;
            }
        }
        printf("Case #%d: %lld\n", ii, ans);
    }
}

调Bug闲聊

一直改不对,一开始是dp数组没初始化,后来初始化没干净,都初始化了也没找到哪里错了,后来是dp数组放前面初始化了。放到后面就初始化干净的原因是,b数组初始化的有点问题导致引用到上一个状态的dp数组,而上一个状态的dp数组没有完全初始化。现在想起来能调出来是真的离谱。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值