吉哥系列故事——临时工计划Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 2794 Accepted Submission(s): 1081Problem Description
俗话说一分钱难倒英雄汉,高中几年下来,吉哥已经深深明白了这个道理,因此,新年开始存储一年的个人资金已经成了习惯,不过自从大学之后他不好意思再向大人要压岁钱了,只能把唯一的希望放到自己身上。可是由于时间段的特殊性和自己能力的因素,只能找到些零零碎碎的工作,吉哥想知道怎么安排自己的假期才能获得最多的工资。
已知吉哥一共有m天的假期,每天的编号从1到m,一共有n份可以做的工作,每份工作都知道起始时间s,终止时间e和对应的工资c,每份工作的起始和终止时间以天为单位(即天数编号),每份工作必须从起始时间做到终止时间才能得到总工资c,且不能存在时间重叠的工作。比如,第1天起始第2天结束的工作不能和第2天起始,第4天结束的工作一起被选定,因为第2天吉哥只能在一个地方工作。
现在,吉哥想知道怎么安排才能在假期的m天内获得最大的工资数(第m+1天吉哥必须返回学校,m天以后起始或终止的工作是不能完成的)。Input
第一行是数据的组数T;每组数据的第一行是2个正整数:假期时间m和可做的工作数n;接下来n行分别有3个正整数描述对应的n个工作的起始时间s,终止时间e,总工资c。[Technical Specification]
1<=T<=1000
9<m<=100
0<n<=1000
s<=100, e<=100, s<=e
c<=10000Output
对于每组数据,输出吉哥可获得的最高工资数。Sample Input
1
10 5
1 5 100
3 10 10
5 10 100
1 4 2
6 12 266Sample Output
102
这道题有点像<尼克的任务>,比《尼克的任务》简单,对终止时间dp,得状态转移方程dp[j]=max{dp[j],dp[s[i]-1]+w[i]};
代码:
1 #include <stdio.h>
2 #include <string.h>
3 #include <algorithm>
4 #include <iostream>
5 using namespace std;
6
7 struct mem{
8 int s, e, w;
9 }a[1005];
10
11 bool cmp(mem a,mem b)
12 {
13 return a.e<b.e;
14 }
15 main()
16 {
17 int n, i, j, k, t, x, y, z, m, dp[110];
18 cin>>t;
19 while(t--)
20 {
21 cin>>m>>n;
22 k=0;
23 for(i=0;i<n;i++)
24 {
25 scanf("%d %d %d",&x,&y,&z);
26 if(x<1||x>m||y>m) continue;
27 a[k].s=x;
28 a[k].e=y;
29 a[k++].w=z;
30 }
31 sort(a,a+k,cmp);
32 memset(dp,0,sizeof(dp));
33 for(i=0;i<k;i++)
34 {
35 for(j=m;j>=a[i].e;j--)
36 dp[j]=max(dp[j],dp[a[i].s-1]+a[i].w);
37 }
38 printf("%d\n",dp[m]);
39 }
40 }
顺便贴上尼克的任务:
尼克的任务【动态规划专项练习赛】——高级
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 29 Accepted: 17
Description尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。
尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去写成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。
写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。
Input输入数据第一行包含两个用空格隔开的整数N和K,1≤N≤10000,1≤K≤10000,N表示尼克的工作时间,单位为分,K表示任务总数。
接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从第P分钟开始,持续时间为T分钟,其中1≤P≤N,1≤P+T-1≤N。
Output
输出文件仅一行包含一个整数表示尼克可能获得的最大空暇时间。
Sample Input15 6
1 2
1 6
4 11
8 5
8 1
11 5
Sample Output4
这道题不容易想(我没想出来。。。),看了大神的代码,才知道这道题是倒推。。动态规划经常做正推的,实在是想不出来。。。
分析:
设dp[i]为从i-n时间段内最大空暇时间,那么如果第i分钟时没有任务,那么dp[i]=dp[i+1]+1;
如果第i分钟有或者有多个任务,设i分钟时有k个起始任务,那么dp[i]=max(dp[i],dp[i+T[i]]);
代码:
1 #include <stdio.h>
2 #include <iostream>
3 #include <algorithm>
4 #include <string.h>
5 #include <vector>
6 using namespace std;
7
8 main()
9 {
10 vector<int>time[10005];
11 int n, k, i, j, a, b, dp[10005];
12 scanf("%d %d",&n,&k);
13 for(i=1;i<=k;i++)
14 {
15 scanf("%d %d",&a,&b);
16 time[a].push_back(b);
17 }
18 memset(dp,0,sizeof(dp));
19 for(i=n;i>=1;i--)
20 {
21 if(time[i].empty())
22 dp[i]=dp[i+1]+1;
23 else {
24 for(j=0;j<time[i].size();j++)
25 dp[i]=max(dp[i],dp[i+time[i][j]]);
26 }
27 }
28 printf("%d\n",dp[1]);
29 }
HDU 4502吉哥系列故事——临时工计划 和 《尼克的任务》