POJ 2228. Naptime

Link
题意:
在一天 \(n\) 个小时中取 \(b\) 个小时,使权值和最大,\(b\) 个小时可分成若干段,每段的第一个小时的权值不计入总和,第 \(n\) 个小时与第一个小时相连
思路:
\(f[i][j][0]\) 为前 \(i\) 个小时中睡了 \(j\) 个小时且第 \(i\) 个小时不在睡,\(f[i][j][1]\) 为前 \(i\) 个小时中睡了 \(j\) 个小时且第 \(i\) 个小时在睡
转移方程:
\( \begin{cases} f[i][j][0]=\max(f[i-1][j][0],f[i-1][j][1]) \\ f[i][j][1]=\max(f[i-1][j-1][0],f[i-1][j-1][1]+w[i]) \end{cases} \)
因为首尾相连,所以第 \(n\) 个小时会影响第一个小时
当第 \(n\) 个小时没有睡:\(f[1][0][0]=f[1][1][1]=0\),结果为 \(f[n][b][0]\)
当第 \(n\) 个小时在睡:\(f[1][0][0]=0,f[1][1][1]=w[1]\),结果为 \(f[n][b][1]\)
取最大值
代码:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
typedef long long ll;
typedef pair<int,int> pii;

const int N=4000;
int w[N];
int f[N][2];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,b;
    cin>>n>>b;
    for(int i=1;i<=n;i++) cin>>w[i];
    memset(f,0xc0,sizeof f);
    f[0][0]=f[1][1]=0;
    for(int i=2;i<=n;i++)
        for(int j=min(i,b);j>=0;j--) {
            f[j][0]=max(f[j][0],f[j][1]);
            if(j) f[j][1]=max(f[j-1][0],f[j-1][1]+w[i]);
        }
    int res=f[b][0];
    memset(f,0xc0,sizeof f);
    f[0][0]=0,f[1][1]=w[1];
    for(int i=2;i<=n;i++)
        for(int j=min(i,b);j>=0;j--) {
            f[j][0]=max(f[j][0],f[j][1]);
            if(j) f[j][1]=max(f[j-1][0],f[j-1][1]+w[i]);
        }
    res=max(res,f[b][1]);
    cout<<res<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/c4Lnn/p/12596177.html
POJ