P1280 尼克的任务
题目描述
尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。
尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去完成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。
写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。
输入输出格式
输入格式:输入数据第一行含两个用空格隔开的整数N和K(1≤N≤10000,1≤K≤10000),N表示尼克的工作时间,单位为分钟,K表示任务总数。
接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从第P分钟开始,持续时间为T分钟,其中1≤P≤N,1≤P+T-1≤N。
输出格式:输出文件仅一行,包含一个整数,表示尼克可能获得的最大空暇时间。
输入输出样例
让我来讲一下这个题目为什么要倒着推!!!这一题可是难死我了,个人认为此题最最最重要的就是看清楚题意,也就是此时有任务(不在工作状态)就必须选,有很多个就选一个,所以当这个时间只有一个状态开始的时候,我们是没有任何的话说的,但是如果有很多的任务同时开始,我们要选取最优的那个取决这个任务结束后的情况,但是任务结束后的情况我们之前有没有推过,所以我们要倒着推。
ac代码:
参考题解:http://blog.csdn.net/clove_unique/article/details/50448940
http://blog.csdn.net/ly59782/article/details/52006319
http://blog.csdn.net/sdfzyhx/article/details/52027745
#include<bits/stdc++.h>
using namespace std;
struct work
{
int x,y;
}a[10001];
bool complare(work p,work q)
{
return p.x<q.x;
}
int f[10001];
int main()
{
int n,k;cin>>n>>k;
for(int i=1;i<=k;++i) cin>>a[i].x>>a[i].y;
sort(a+1,a+1+k,complare);
int j=k;
下面是关键:
for(int i=n;i>=1;--i)
{
cout<<"i="<<i<<" ";
if(i!=a[j].x){f[i]=f[i+1]+1;cout<<"f["<<i<<"]="<<f[i]<<" ";}
else
{
while(i==a[j].x)
{
f[i]=max(f[i],f[i+a[j].y]); //此处f[i]并非由f[i+1]推出,而是在前面的所有结果中作选择。从这里可以思考一下贪心与dp的区别。或者说dp是怎么得到最优解的。
j--;
cout<<"f["<<i<<"]="<<f[i]<<" ";
}
}
cout<<endl;
}
cout<<f[1];
return 0;
}
最后补充:正推也可以做,但感觉实在不太好考虑。