P1280 尼克的任务

题意:

尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。

当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,

尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,

则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,

则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,

则该任务将在第P+T-1分钟结束。

写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间

一道普及难度的题

我居然想不到正解!!

我TMDP太弱了。。。

还是要多练啊。。。

设f[i]:1~i的最大空闲时间,但是,第i时刻的最大空闲时间是和后面i+1选择任务的持续时间的时刻有关系的(有后效性),那么,正着找肯定是不行的,

我们来试一下倒着搜,即设f[i]表示i~n的最大空闲时间,经尝试,发现是完全可行的,可以列出动态转移方程如下

(本时刻无任务)f[i]=f[i+1]+1;//继承上一个时刻的最大空闲时间后+1

(本时刻有任务)f[i]=max(f[i],f[i+a[sum])//a[sum]表示在这个时刻的任务的持续时间,找出选择哪一个本时刻任务使空闲时间最大化

那么既然是倒着搜,从后往前的任务对应的开始时间自然也要反过来,从大到小排序(同时也是为了把相同开始时间的任务放到一起),

当然在进行状态刷新的时候别忘了拿sum不断计一下已经到哪一个任务了

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define love_nmr 0
int n,k;
struct node
{
    int beg;
    int dis;
    friend bool operator < (const node &a,const node &b)
    {
        return a.beg>b.beg;
    }
}w[10505];
int f[10505];
int t[10505];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        cin>>w[i].beg>>w[i].dis;
        t[w[i].beg]++;
    }
    sort(w+1,w+k+1);
    int ji=1;
    for(int i=n;i>=1;i--)
    {
        if(!t[i])
            f[i]=f[i+1]+1;
        else
        {
            for(int j=1;j<=t[i];j++)
            {
                if(f[i]<f[i+w[ji].dis])
                    f[i]=f[i+w[ji].dis];
                ji++;
            }
        }
    }
    cout<<f[1];
    return 0;

}
原文地址:https://www.cnblogs.com/olinr/p/9445618.html