poj2228 Naptime

/*
 * 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;                    
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章