P1280 尼克的任务
P1280 尼克的任务 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
按正常思路来想:
首先令dp[ i ]为到第i分钟的最多空闲时间,讲第i分钟结尾的工作时间存入 v[ i ]。
容易获得代码:
for(int i=1;i<=m;i++) { int st=read(),t=read(); v[st].pb(t); }for(int i=1;i<=n;i++) { if(!v[i].size()) dp[i]=dp[i-1]+1; else for(auto x:v[i]) dp[i+x]=max(dp[i],dp[i+x]); } printf("%d",dp[n]);
但显然这是dp[i]推dp[i+x],显然是不符合dp的
那么为什么倒着推?
此时有任务(不在工作状态)就必须选,有很多个就选一个,所以当这个时间只有一个状态开始的时候,我们是没有任何的话说的
但是如果有很多的任务同时开始,我们要选取最优的那个取决这个任务结束后的情况,但是任务结束后的情况我们之前有没有推过,所以我们要倒着推
dp[i]=max(dp[i],dp[i+x]),正推的话dp[i+x]是不知道的
倒推:dp[i]为第i分钟开始所能获得的最多空闲时间
for(int i=1;i<=m;i++) { int st=read(),t=read(); v[st].pb(t); } for(int i=n;i;i--) { if(!v[i].size()) dp[i]=dp[i+1]+1; else for(auto x:v[i]) dp[i]=max(dp[i],dp[i+x]); } printf("%d",dp[1]);
完整code:
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back #define popb pop_back #define fi first #define se second const int N=1e4+10; //const int M=; //const int inf=0x3f3f3f3f; //const ll INF=0x3ffffffffffff; int T,n,m,dp[N]; vector<int> v[N]; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { // freopen("","r",stdin); // freopen("","w",stdout); n=read(),m=read(); for(int i=1;i<=m;i++) { int st=read(),t=read(); v[st].pb(t); } for(int i=n;i;i--) { if(!v[i].size()) dp[i]=dp[i+1]+1; else for(auto x:v[i]) dp[i]=max(dp[i],dp[i+x]); } printf("%d",dp[1]); return 0; }