时间表

4s / 256M

【题目描述】
为了提高效率,ml 觉得需要合理规划一下自己每天的时间表了。ml 把一天分为了 n 各
时段,在每个时段内他可以选择做事情或者是休息,一个时段只能做一次选择。因为要劳逸
结合,所以 ml 规定每天至多有 b 个时段用来做事情,其余时间用来休息。如果 ml 在时段 i
选择做事情,他将获得 Ui 的收获,否则他将没有收获。
但特殊情况是,在每几个连续的做事情的时段中,ml 在第一个时段的状态会很差,所
以连续的做事情的时段中第一个时段的收获为 0。还有,每一天都是连续的,即如果 ml 在
第 n 个时段和第一个时段都选择做事情,那么他在第一个时段会获得相应的收获(第 n 个时
段视它前面的情况而定)

下面的问题是就是如何安排这 b 个时段,使得每天的收获最大?
【输入文件】
第 1 行:空格格开的两个整数 n 和 b
第 2-n+1 行:每行一个整数,第 i+1 行代表 Ui
【输出文件】
一行一个整数,表示 ml 每一天能得到的最大收获
【输入样例】
5 3
2
0
3
1
4
【输出样例】
6
【数据规模和约定】
对于 40%的数据,n<=20
对于 100%的数据,3<=n<=3830,2<=b<=n,0<=Ui<=200000
【样例提示】
一天被分为 5 个时段,收获依次为 2, 0, 3, 1, 4。
ml 选择在时段 4,5,1 做事情,收获为 0+4+2=6

假如说第一天和第 N 天不是连续的,那就是简单的二维 dp,即用
f[i][j][k]表示到第 i 天,已经选取了 j 天,第 i 天的状态为 0 或 1(选或不选)的最大收益

f[x][j][0]=max(f[y][j][0],f[y][j][1])
f[x][j][1]=max(f[y][j-1][0],f[y][j-1][1]+u[i])
x=i,y=i-1
并注意到 f[i][0][1]是不存在的,即赋成-inf
循环了怎么办?那就分类讨论,第 n 天选或 不选即可,
不选 f[0][0][1]=-inf,ans=f[n][b][0]
选 f[0][0][1]=0,ans=f[n][b][1](这样f[1][1][1]就会等于u[1])
注意分情况,分状态,由简入繁,不会时先想想简单情况,有时候复
杂的东西稍微一讨论就出来了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 int f[2][4001][2],ans,n,m,now,nxt,a[4001],inf=2e9;
 8 int main()
 9 {int i,j;
10     cin>>n>>m;
11     for (i=1;i<=n;i++)
12     scanf("%d",&a[i]);
13     memset(f,0,sizeof(f));
14     now=0;nxt=1;
15     f[0][0][0]=0;
16     f[0][0][1]=-inf;
17     for (i=1;i<=n;i++)
18     {
19         f[nxt][0][1]=-inf;
20         for (j=0;j<=m;j++)
21         {
22             f[nxt][j][0]=max(f[now][j][0],f[now][j][1]);
23             if (j)
24             f[nxt][j][1]=max(f[now][j-1][0],f[now][j-1][1]+a[i]);
25         }
26         memset(f[now],0,sizeof(f[now]));
27         swap(now,nxt);
28     }
29     ans=f[now][m][0];
30     memset(f,0,sizeof(f));
31     now=0;nxt=1;
32     for (i=1;i<=n;i++)
33     {
34         f[nxt][0][1]=-inf;
35         for (j=0;j<=m;j++)
36         {
37             f[nxt][j][0]=max(f[now][j][0],f[now][j][1]);
38             if (j)
39             f[nxt][j][1]=max(f[now][j-1][0],f[now][j-1][1]+a[i]);
40         }
41         memset(f[now],0,sizeof(f[now]));
42         swap(now,nxt);
43     }
44     ans=max(ans,f[now][m][1]);
45     cout<<ans;
46 }

 

posted @ 2017-10-25 16:59  Z-Y-Y-S  阅读(363)  评论(0编辑  收藏  举报