洛谷 P1280(逆向dp)
题目描述
尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。
尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。
写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。
输入格式
输入数据第一行含两个用空格隔开的整数N和K(1≤N≤10000,1≤K≤10000),N表示尼克的工作时间,单位为分钟,K表示任务总数。
接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从第P分钟开始,持续时间为T分钟,其中1≤P≤N,1≤P+T-1≤N。
输出格式
输出文件仅一行,包含一个整数,表示尼克可能获得的最大空暇时间。
输入输出样例
输入 #1
15 6 1 2 1 6 4 11 8 5 8 1 11 5
输出 #1
4
正向推感觉很困难,看了正向推的题解也还是不是太明白。逆向推相对就好理解多了。 dp[i] 表示以时间 i 开始工作到 n 的最大空闲时间,那么有:
当 i 不是工作开始的时间时,dp[i] = dp[i + 1] + 1,( 没有任务要选,当然是选择休息 )
i 是工作时间而且可能有多个,但是只需要选一个,那么 dp[i] = max(dp[i],dp[i + p[i].se])
#include<bits/stdc++.h> #define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl #define pii pair<int,int> #define clr(a,b) memset((a),b,sizeof(a)) #define rep(i,a,b) for(int i = a;i < b;i ++) #define pb push_back #define MP make_pair #define LL long long #define ull unsigned LL #define ls i << 1 #define rs (i << 1) + 1 #define fi first #define se second #define ptch putchar #define CLR(a) while(!(a).empty()) a.pop() using namespace std; inline LL read() { LL s = 0,w = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') w = -1; ch = getchar(); } while(isdigit(ch)) s = s * 10 + ch - '0',ch = getchar(); return s * w; } inline void write(LL x) { if(x < 0) putchar('-'), x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } const int maxn = 10010; pii p[maxn]; int dp[maxn]; bool cmp(pii A,pii B){ if(A.fi != B.fi) return A.fi < B.fi; return A.se < B.se; } int main() { //#ifndef ONLINE_JUDGE // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); //#endif int n = read(),k = read(); for(int i = 1;i <= k;++ i){ p[i].fi = read(); p[i].se = read(); } sort(p + 1,p + 1 + k,cmp); int cnt = k; for(int i = n;i >= 1;-- i){ if(p[cnt].fi != i) dp[i] = dp[i + 1] + 1; else { while(cnt >= 1 && p[cnt].fi == i){ dp[i] = max(dp[i],dp[i + p[cnt].se]); -- cnt; } } } write(dp[1]); ptch('\n'); return 0; }