P1280

2024-02-10 12:58
文章标签 p1280

本文主要是介绍P1280,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

P1280 尼克的任务

思路

思考线程1

这题自己还是没有想出来该怎么做,这道题其实刚开始理解一下是可以从任务的角度去dp?就是类似前面的最长子序列一样dp[n],但是题解上基本都是按dp[T]来的,这个选择就很让人费解,首先知道,题目问什么dp数组就存什么东西,但这个下标的选取并没有很强的规律性,只能启发式的总结成题目中数值形的且按小单位递增的东西,例如钱和时间.然后是这个dp转移方程的理解:
如 果 该 时 刻 s t [ i ] = = 0 则 d p [ i ] = d p [ i + 1 ] + 1 如果该时刻st[i] == 0 则dp[i]=dp[i+1]+1 st[i]==0dp[i]=dp[i+1]+1
如 果 该 时 刻 s t [ i ] ! = 0 则 d p [ i ] = m a x ( d p [ i + m i s s i o n [ j ] . d u r a t i o n ] , d p [ i ] ) 如果该时刻st[i] != 0 则dp[i] = max(dp[i+mission[j].duration], dp[i]) st[i]!=0dp[i]=max(dp[i+mission[j].duration],dp[i])
但是怎么理解这两个转移方程和题目问的

尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。

主要难点在于为什么顺推不行,而倒推就可以,首先顺推不行是因为在某个状态dp[i],这一刻选择的任务必然会影响到之后的选择,(如果做类比的话,原来背包问题dp[i]= max(dp[i], dp[i - item.cost]+item.value)这里是i-item.cost,是从之前的格子转移过来的,所以必须顺推,但是好像也不能这么理解,0-1背包的内层循环就是逆推的,

思考线程2

假设自己已经聪明到用dp[i]代表i-T的最大空余时间而且义无反顾的用了逆推,那么 d p [ i ] = d p [ i + 1 ] + 1 dp[i] = dp[i+1]+1 dp[i]=dp[i+1]+1这个式子能顺理成章的推出来吗,就是相当于此刻没有任务,这个还是能够想清的,然后是 d p [ i ] = m a x ( d p [ i ] , d p [ i + m i s s i o n [ j ] . d u r a t i o n ] ) dp[i] = max(dp[i], dp[i+mission[j].duration]) dp[i]=max(dp[i],dp[i+mission[j].duration]),这个转移能看懂,主要是怎么解决的向后影响的问题,因为题目不是说如果当前在做着任务,就不用考虑新的任务吗!!!不用管,因为首先当前考虑的任务的选择不会影响之后的选择(但这个不具有共性,最长不下降的选择和背包的选择自然会影响后面的选择,不然也不叫动态规划了,所以并不能说不会影响之后的选择,关键是理解这个状态的

思考线程3(第二天了)

就是说更新转态的话,那么出现在等式右边的状态必然要在之前就被更新,不然就不叫状态转移方程了呗.完事

code

#include <algorithm>
#include <bits/stdc++.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;
const int maxn = 100000+5;
int dp[maxn];
struct node
{int start;int duration;bool operator < (const node&b) const{return start<b.start;}
};
node mission[100000+5];
int main() 
{
#ifdef LOCALfreopen("C:\\Users\\hsxny\\Desktop\\in.txt", "r", stdin);
#endif
int N,K;
int st[10000+5]={0};
scanf("%d%d",&N,&K);
for(int i=0;i<K;i++)
{node& temp = mission[i];scanf("%d%d",&temp.start, &temp.duration);st[temp.start]++;
}
sort(mission, mission+K);for(int i=N;i>=1;i--)
{if(st[i] == 0){dp[i] = dp[i+1]+1;}else{for(int j=1;j<=K;j++){if(mission[j].start==i)    dp[i]= max(dp[i+mission[j].duration],dp[i]);        }}
}printf("%d", dp[1]);
return 0;
}

这篇关于P1280的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/697162

相关文章

『经典DP入门』洛谷 P1280 尼克的任务

『题目描述』 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。 尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某

DP 洛谷 P1280 尼克的任务

题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。 尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开