nowcoder17338 Interval Revisited

链接

点击跳转

题解

分析题目,如果一种方案中,某个点上覆盖了三条线段,那么肯定有一条线段即使去掉也能让剩下的线段覆盖整个区间,而且答案只可能变优而不可能变劣。

所以可以得出一个结论:一个点上面最多有两条线段

那么方案也就长这样:在这里插入图片描述

先把线段按照右端点排序,然后开始 d p dp dp

d p [ i ] [ j ] dp[i][j] dp[i][j]表示强制选择第 i i i条线段,从 1 1 1到这条线段的右端都被覆盖了,而且从这个线段的左端点到 j − 1 j-1 j1这个坐标都是被覆盖了两次的区间。满足以上条件的最小答案。

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 2020
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct Segment
{
    ll l, r, w;
}seg[maxn];
ll dp[maxn][maxn];
int main()
{
    ll T=read();
    while(T--)
    {
        ll n=read(), m=read(), i, j, ans=linf;
        rep(i,1,n)seg[i].l=read(), seg[i].r=read(), seg[i].w=read();
        sort(seg+1,seg+n+1,[](Segment s1, Segment s2){return s1.r<s2.r;});
        rep(i,0,n)rep(j,0,m+1)dp[i][j]=linf;
        dp[0][1]=0;
        rep(i,1,n)
        {
            rep(j,0,i-1)
            {
                ll t=linf;
                if(seg[i].l<=seg[j].r)t=max(dp[j][seg[i].l],seg[j].w+seg[i].w);
                else if(seg[i].l==seg[j].r+1)t=max(dp[j][seg[i].l],seg[i].w);
                dp[i][seg[j].r+1]=min(dp[i][seg[j].r+1],t);
            }
            rep(j,seg[i].l+1,seg[i].r+1)dp[i][j]=min(dp[i][j],dp[i][j-1]);
            if(seg[i].r==m)ans=min(ans,dp[i][m+1]);
        }
        if(ans==linf)printf("-1\n");
        else printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值