没看过其他人的代码,所以我就用了记忆化搜索去写这道线性DP
反正就是无聊试试(ーー゛)没想到就给过了233
我的做法:用链式前向星记录某个在有工作开始的时间点做了从它开始的工作后可到达的时间点(不能超过N+1),
如果某个时间点没有工作开始,就用一个数组记录它的下一个有工作开始的时间点。
搜索的时候如果当前时间点有工作开始就枚举每项工作并跳到该工作结束的时间点;
如果没有就跳到下一个有工作开始的时间点,空闲时间+=跳过的时长。边界条件是当前时间==N+1。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 3 struct l 4 { 5 int to,next; 6 } edge[10010]; 7 int shi,geshu,zhizhen=0,head[10010],xyg[10010],jiyi[10010]; 8 9 int max(int a,int b) 10 { 11 return a>b?a:b; 12 } 13 14 int min(int a,int b) 15 { 16 return a<b?a:b; 17 } 18 19 void add(int from,int to) 20 { 21 zhizhen++; 22 edge[zhizhen].to=to; 23 edge[zhizhen].next=head[from]; 24 head[from]=zhizhen; 25 } 26 27 int search(int sj,int shu) 28 { 29 if(sj==shi+1) return shu; 30 if(jiyi[sj]!=0) 31 { 32 if(jiyi[sj]==-1) return shu; 33 else return jiyi[sj]+shu; 34 } 35 int n,lj; 36 if(head[sj]!=0) 37 { 38 for(n=head[sj]; n!=0; n=edge[n].next) 39 { 40 lj=edge[n].to; 41 jiyi[sj]=max(jiyi[sj],search(lj,shu)-shu); 42 } 43 } 44 else jiyi[sj]=max(jiyi[sj],search(xyg[sj],shu+xyg[sj]-sj)-shu); 45 if(jiyi[sj]==0) 46 { 47 jiyi[sj]=-1; 48 return shu; 49 } 50 else return jiyi[sj]+shu; 51 } 52 53 int main() 54 { 55 int n,a,b,ans; 56 scanf("%d%d",&shi,&geshu); 57 for(n=1; n<=geshu; n++) 58 { 59 scanf("%d%d",&a,&b); 60 add(a,min(a+b,shi+1)); 61 } 62 a=shi+1; 63 for(n=shi; n>=1; n--) 64 { 65 if(head[n]!=0)a=n; 66 else xyg[n]=a; 67 } 68 ans=search(1,0); 69 printf("%d ",ans); 70 return 0; 71 }