/*
* 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.