洛谷 P1280 尼克的任务(dp)
传送门
解题思路
因为正序不好推,所以我们倒序:
dp[i]表示从时间i到最终时刻n的最大休息时间,所以我们可以推出以下的状态转移方程:
- 若i时刻无任务,则dp[i]=dp[i+1]+1;
- 若i时刻有至少一个任务,则枚举这些任务k,dp[i]=dp[a[k]+b[k]];(a,b为题目中读入的每个任务的起始时间和时长)。
最终答案即为dp[1]。
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=10005; 5 int n,t,dp[maxn],cnt=1; 6 struct node{ 7 int b,e,w; 8 }a[maxn]; 9 bool cmp(node x,node y){ 10 return x.b!=y.b?x.b>y.b:x.e<y.e; 11 } 12 int main(){ 13 cin>>n>>t; 14 for(int i=1;i<=t;i++){ 15 cin>>a[i].b>>a[i].w; 16 a[i].e=a[i].b+a[i].w-1; 17 } 18 sort(a+1,a+t+1,cmp); 19 for(int i=n;i>=1;i--){ 20 if(cnt>t||a[cnt].b<i) dp[i]=dp[i+1]+1; 21 else{ 22 while(cnt<=t&&a[cnt].b>=i) dp[i]=max(dp[i],dp[a[cnt++].e+1]); 23 } 24 } 25 cout<<dp[1]; 26 return 0; 27 }