nowcoder多校4B(DP)

这题比较考验思维。。看了咖啡鸡的转移就秒懂了 。。

首先显然每个点最多被2个区间覆盖。。

然后在加入区间的时候就必须保证每个点最多被覆盖2次,不然不是最优。。

其实这个性质给DP带来了不少便利。。少考虑了很多情况。。。在加入区间的同时需要知道最后覆盖了2个点的坐标。。

所以可以这么设计。。设d[i][j]为取第i个区间且j-r[i]只被覆盖一次的最小值。。

然后d[i][j]并不需要被全扫出来。。只要通过前i-1个区间转移到i的一些状态就行。。而这些状态已经涵盖了所有的情况。。

转移见代码更容易理解。。

 

 

/**
 *          ┏┓    ┏┓
 *          ┏┛┗━━━━━━━┛┗━━━┓
 *          ┃       ┃  
 *          ┃   ━    ┃
 *          ┃ >   < ┃
 *          ┃       ┃
 *          ┃... ⌒ ...  ┃
 *          ┃              ┃
 *          ┗━┓          ┏━┛
 *          ┃          ┃ Code is far away from bug with the animal protecting          
 *          ┃          ┃   神兽保佑,代码无bug
 *          ┃          ┃           
 *          ┃          ┃        
 *          ┃          ┃
 *          ┃          ┃           
 *          ┃          ┗━━━┓
 *          ┃              ┣┓
 *          ┃              ┏┛
 *          ┗┓┓┏━━━━━━━━┳┓┏┛
 *           ┃┫┫       ┃┫┫
 *           ┗┻┛       ┗┻┛
 */ 
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 2005
#define nm 400000
#define N 1000005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const int inf=1e9+7;
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}



struct tmp{
    int l,r,w;
    bool operator<(const tmp&o){return r<o.r;}
}a[NM];
int n,m,d[NM][NM],f[NM][NM],ans;

int main(){
    int _=read();while(_--){
	n=read();m=read();ans=inf;
	inc(i,1,n)a[i].l=read(),a[i].r=read(),a[i].w=read();
	sort(a+1,a+1+n);
	inc(i,1,n){
	    inc(j,0,m)d[i][j]=f[i][j]=inf;
	    if(a[i].l==1)inc(j,1,a[i].r)d[i][j]=a[i].w;
	    inc(j,1,m)f[i][j]=min(d[i][j],f[i][j-1]);
	}
//	inc(i,1,n)printf("%d %d %d\n",a[i].l,a[i].r,a[i].w);
//	inc(i,1,n){inc(j,1,m)printf("%d ",d[i][j]);putchar('\n');}
	inc(i,1,n){
	    inc(j,1,i-1)if(a[i].l==a[j].r+1)d[i][a[i].l]=min(d[i][a[i].l],max(f[j][m],a[i].w));
	    else if(a[i].l<=a[j].r)d[i][a[j].r+1]=min(d[i][a[j].r+1],max(f[j][a[i].l],a[i].w+a[j].w));
	    inc(j,1,m)f[i][j]=min(f[i][j-1],d[i][j]);
	}
//	inc(i,1,n){inc(j,1,m)printf("%d ",d[i][j]);putchar('\n');}
	dec(i,n,1)if(a[i].r==m)ans=min(ans,f[i][m]);else break;
	if(ans<inf)printf("%d\n",ans);else printf("-1\n");
    }
    return 0;
}

 

 

Interval Revisited

链接:https://www.nowcoder.com/acm/contest/142/B
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

Chiaki has a long interval [1,m] and n small intervals [l1, r1], [l2,r2], ..., [ln, rn]. Each small interval [li,ri] is associated with a weight wi.
Chiaki would to select some small intervals such that:

  • each integer position x ∈ [1, m] is covered by at least one small interval.
  • let sx be the sum of the weights of all the small intervals covering position x, the maximum value of sx should be minimum.

Chiaki would like to know the minimum value of maximum sx.

输入描述:

There are multiple test cases. The first line of input contains an integer T, indicating the number of test
cases. For each test case:
The first line contains two integers n and m (1 ≤ n, m ≤ 2000) -- the number of small intervals and the length of the long interval.
Each of the next n lines contains three integers li, ri and wi (1 ≤ li ≤ ri ≤ m, 1 ≤ wi ≤ 1000).
It is guaranteed that the sum of all n does not exceed 20000.

输出描述:

For each test case, output an integer denoting the answer, or -1 if Chiaki cannot select such intervals.

示例1

输入

复制

2
2 4
1 2 2
3 4 5
1 4
1 3 1

输出

复制

5
-1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值