P1280 尼克的任务
传送门
思路:
动态规划:设 f [ i ] 表示第 i 个任务开始时,可获得的最大空闲时间。
转移方程:
① 若此时无任务:f [ i ] = max( f [ i ] , f [ i-1 ]+1 )。
② 若此时有任务:f [ i+wj-1 ] = max( f [ i+wj-1 ] , f [ i-1 ] )。
注:有任务时,用 j 枚举开始的时间为 i 的任务,提前更新掉第 j 个任务结束的时间 i+wj-1 的 f [ i+wj-1 ]。
标程:
#include<iostream> #include<cmath> #include<cstring> #include<cstdio> #include<string> #include<cstdlib> #include<algorithm> #include<stack> #include<vector> #include<queue> #include<deque> #include<map> #include<set> using namespace std; #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define maxn 10001 #define INF -0x3f typedef long long LL; LL n,k; LL f[maxn]; struct hh { LL l,w; }t[maxn]; inline LL read() { LL xs=0,kr=1;char ls; ls=getchar(); while(!isdigit(ls)) { if(!(ls^45)) kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return xs*kr; } int main() { memset(f,INF,sizeof(f)); n=read();k=read(); for(LL i=1;i<=k;i++) t[i].l=read(),t[i].w=read(); LL j=0;f[0]=0; for(LL i=1;i<=n;i++) { if(t[j+1].l!=i) f[i]=max(f[i],f[i-1]+1); while(j<k&&t[j+1].l==i) { j++;//j不断增加,即枚举任务。 f[i+t[j].w-1]=max(f[i+t[j].w-1],f[i-1]); } } printf("%lld\n",f[n]); return 0; }