【codevs 1158】尼克的任务

1158 尼克的任务
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
查看运行结果
题目描述 Description
尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。
尼 克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来 做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去写成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如 果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。
写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。

输入描述 Input Description
输入数据第一行包含两个用空格隔开的整数N和K,1≤N≤10000,1≤K≤10000,N表示尼克的工作时间,单位为分,K表示任务总数。
接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从第P分钟开始,持续时间为T分钟,其中1≤P≤N,1≤P+T-1≤N。

输出描述 Output Description
输出文件仅一行包含一个整数表示尼克可能获得的最大空暇时间。

样例输入 Sample Input
15 6
1 2
1 6
4 11
8 5
8 1
11 5

样例输出 Sample Output
4

dp大法好
一共有k个任务,在当前空闲时刻只有一个任务则必须做,多个任务选一个
首先考虑正向dp,对于只有一个的任务必须选择,做这个任务时的最大空闲时间与做任务之前相同
对于多个任务可以分别转移再到下一个判max
然而QAQ你会发现这个麻烦死
so……我们重新考虑

对于当前状态影响它的只会是它上一个状态
下一个状态再由它更新
嗯嗯所以就是你了——
逆向dp
这样状态更新就唯一啦~

#include 
#include 
#include 
#include 
using namespace std;
const int MAXN = 10005;
int n,k,dp[MAXN];//dp[i],当前时刻为i的最大空闲
struct dc{
    int l,t;
}num[MAXN];

void dpdpd(){
    int xc = k;
    for(int i = n; i >= 1; i --){
        if(num[xc].l == i)//有>= 1的任务
            while(num[xc].l == i){
                if(dp[i] < dp[i + num[xc].t])
                    dp[i] = dp[i + num[xc].t];
                xc --;
            }   
        else if(num[xc].l != i)//没有任务 
            dp[i] = dp[i + 1] + 1;
    }
}

int main(){
    memset(num,0,sizeof(num));
    memset(dp,0,sizeof(dp));
    scanf("%d %d",&n,&k);
    for(int i = 1; i <= k; i ++)
        scanf("%d %d",&num[i].l,&num[i].t);
    dpdpd();    printf("%d\n",dp[1]);//倒着更新的所以输出的是第一个
    return 0;
}

你可能感兴趣的:(===动态规划===)