https://www.luogu.com.cn/problem/P1280
所谓无后效性原则,指的是这样一种性质:某阶段的状态一旦确定,则此后过程的演变不再受此前各状态及决策的影响。也就是说,“未来与过去无关”,当前的状态是此前历史的一个完整总结,此前的历史只能通过当前的状态去影响过程未来的演变。具体地说,如果一个问题被划分各个阶段之后,阶段k中的状态只能通过阶段k+1中的状态通过状态转移方程得来,与其他状态没有关系,特别是与未发生的状态没有关系,这就是无后效性。
对于尼克的任务这个题:第一时间想到设f[i]:1~i的最大空闲时间,但是,想了一下之后发现,第i时刻的最大空闲时间是和后面i+选择任务的持续时间的时刻有关系的,原因是这是对未来状态的考量,不符合动态规划的无后效性。
我们来试一下倒着搜,即设f[i]表示i~n的最大空闲时间,经尝试,发现是完全可行的,可以列出动态转移方程如下:
(本时刻无任务)f[i]=f[i+1]+1;//继承上一个时刻的最大空闲时间后+1
(本时刻有任务)f[i]=max(f[i],f[i+a[sum])//a[sum]表示在这个时刻的任务的持续时间,找出选择哪一个本时刻任务使空闲时间最大化
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 int n,k,s,t,f[10002]; 6 vector<int>v[10001]; 7 int main(){ 8 scanf("%d%d",&n,&k); 9 while(k--){ 10 scanf("%d%d",&s,&t); 11 v[s].push_back(t);//记录开始时间相同的任务,结束时间压到vector 12 } 13 for(int i=n;i;--i){ 14 if(v[i].size()>0)//有任务时 15 for(int j=0;j<v[i].size();++j)//把当前时刻的任务数的状态枚举选最优 16 f[i]=max(f[i],f[i+v[i][j]]); 17 else f[i]=f[i+1]+1;//没有任务时, 当前状态结果为上一状态+1 18 } 19 printf("%d",f[1]); 20 }