尼克的任务~动态规划

尼克的任务(0410)

Time limit(ms): 1000
Memory limit(kb): 65535
Submission: 1575
Accepted: 728
Didn't trying
尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。
尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。
写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。
Description
输入数据第一行含一个空格隔开的整数N和K(1≤n≤10000,1≤k≤10000),N表示尼克的工作时间单位为分钟,K表示任务总数。
接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从第P分钟开始,持续时间为T分钟,其中1≤P≤N,1≤P+T-1≤N。
Input
输出文件仅一行,包含一个整数,表示尼克可能获得的最大空暇时间。
Output
1
2
3
4
5
6
7
15 6
1 2
1 6
4 11
8 5
8 1
11 5
Sample Input
1
4

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[20000];//dp[i]表示如果当前在i分钟,我能获得的最大空闲时间
int n,k;
struct sta{
    int start;//开始时间
    int len;//持续时间
};
bool cmp(sta a, sta b)
{
    return a.start > b.start;
}
int main()
{
    while (cin >> n >> k)
    {
        sta data[20000] = { 0 };//储存所有的工作
        memset(dp, 0, sizeof(dp));//默认每一分钟刚开始空闲时间都是0  **
        for (int i = 0; i < k; i++)cin >> data[i].start >> data[i].len;//读取所有工作
        sort(data, data + k,cmp);//工作表按开始时间由大到小排好序,好整理
 
        //从最后一组开始往前
        for (int i = n ,j= 0; i >= 1; i--)//i用于表示当前是多少分钟,j用于标记当前工作时间表读到哪一组了
        {
            if (i != data[j].start)dp[i] = dp[i + 1] + 1;//如果这一分钟没有工作的话,我能比下一分钟多一分钟的空闲
            else {
                //如果当前这一分钟有工作
                while (data[j].start == i)//我就把所有当前时间的工作看一遍
                {
                    //第一次循环到这里的时候,dp[i]还没处理过,i分钟的空闲时间还等于0  **
                    if (dp[i + data[j].len]>dp[i])//dp[i+data[j].len]表示如果我选择当前这个工作,我的空闲时间和i+data[j].len分钟后是一样的,因为在这期间我没有增加空闲时间
                    {
                        //然后比较是我保存的dp[i]的空闲时间多,还是我接受这个工作能获得的空闲时间更多
                        //第一次的时候,i时刻的空闲时间为0,i+data[j].len时刻的空闲时间一定大于0,所以第一份工作是必须接受
                        //然后多次循环,比较后面的在i时刻开始的工作,寻找能获得最大空闲时间的
                        dp[i] = dp[i + data[j].len];
                    }
                    j++;
                }
            }
        }
 
        cout << dp[1] << endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值