/*
* poj2228 AC
* DP+滚动数组
* 方程开始就想错了,看了题解才知道差了十万八千里。
* 值得研究的一道题。
*
* f[i][j][0..1]表示前i段时间,休息j段时间,且第i段时间
* 在不休息(0)或休息(1)时的最大值。
*
* f[i][j][0] = max(f[i-1][j][1],f[i-1][j][0]);
* f[i][j][1] = max(f[i-1][j-1][1]+a[i],f[i-1][j-1][0]);
*
* 但以上方程中,时间段1始终不能取到,所以分两种情况:
* 1) 时间段1不能取到,初始化f[0][0][0] = 0,其他为-INF。
* ans = max(f[n][b][1],f[n][b][1]);
* 2) 时间段1能被取到,初始化f[0][1][1] = 0,其他为-INF。
* ans = max(f[n][b][0],f[n][b][1]+a[1]);
*
* 下面这个解释更加清晰。
* 转自:http://blog.csdn.net/xjwjava/article/details/6778549
*
* 接着考虑circle的问题:
* 有两种方法:1、分情况讨论;2、在1~n后面接上多一段1~n。
* 我是按照第一种方法做的,分三种情况讨论:
* (1)第一段不睡,这样最后一段睡不睡都无所谓:
* 边界为:f[1][0][0] = 0, f[1][1][1] = -INF
* 结果为:max(f[n][b][0], f[n][b][1])
* (2)第一段睡,最后一段也睡:
* 边界为:f[1][1][1] = utility[1], f[1][0][0] = -INF
* 结果为:f[n][b][1]
* (3)第一段睡,最后一段不睡:
* 边界为:f[1][1][1] = 0, f[1][0][0] = -INF
* 结果为:f[n][b][0]
*
* 采用滚动数组节约空间开销。
*
* */
#include<cstdio>
#include<algorithm>
#define INF (1<<30)
using namespace std;
long f[2][3900][2],a[3900];
int main()
{
int n,b,i,j,tmp;
FILE* fin;
fin = fopen("d.in","r");
// scanf("%d%d",&n,&b);
fscanf(fin,"%d%d",&n,&b);
for(i=1;i<=n;i++)
// scanf("%ld",&a[i]);
fscanf(fin,"%ld",&a[i]);
long ans = 0;
for(j=0;j<=b;j++)
f[0][j][1] = f[0][j][0] = -INF;
f[0][0][0] = 0,tmp = 0;
for(i=2;i<=n;i++)
{
for(j=0;j<=b;j++)
f[1-tmp][j][1] = f[1-tmp][j][0] = -INF;
for(j=0;j<=b;j++)
{
f[1-tmp][j][0] = max(f[tmp][j][0],f[tmp][j][1]);
if(j>0)
f[1-tmp][j][1] = max(f[tmp][j-1][0],f[tmp][j-1][1]+a[i]);
}
tmp = 1-tmp;
}
ans = max(f[tmp][b][1],f[tmp][b][0]);
for(j=0;j<=b;j++)
f[0][j][1] = f[0][j][0] = -INF;
f[0][1][1] = 0,tmp = 0;
for(i=2;i<=n;i++)
{
for(j=0;j<=b;j++)
f[1-tmp][j][1] = f[1-tmp][j][0] = -INF;
for(j=0;j<=b;j++)
{
f[1-tmp][j][0] = max(f[tmp][j][0],f[tmp][j][1]);
if(j>0)
f[1-tmp][j][1] = max(f[tmp][j-1][0],f[tmp][j-1][1]+a[i]);
}
tmp = 1-tmp;
}
ans = max(ans,max(f[tmp][b][0],f[tmp][b][1]+a[1]));
printf("%ld\n",ans);
// fclose(fin);
return 0;
}
poj2228 Naptime
最新推荐文章于 2022-02-04 12:45:07 发布