poj2228 Naptime(环形dp)

Description

Goneril is a very sleep-deprived cow. Her day is partitioned into N (3 <= N <= 3,830) equal time periods but she can spend only B (2 <= B < N) not necessarily contiguous periods in bed. Due to her bovine hormone levels, each period has its own utility U_i (0 <= U_i <= 200,000), which is the amount of rest derived from sleeping during that period. These utility values are fixed and are independent of what Goneril chooses to do, including when she decides to be in bed.

With the help of her alarm clock, she can choose exactly which periods to spend in bed and which periods to spend doing more critical items such as writing papers or watching baseball. However, she can only get in or out of bed on the boundaries of a period.

She wants to choose her sleeping periods to maximize the sum of the utilities over the periods during which she is in bed. Unfortunately, every time she climbs in bed, she has to spend the first period falling asleep and gets no sleep utility from that period.

The periods wrap around in a circle; if Goneril spends both periods N and 1 in bed, then she does get sleep utility out of period 1.

What is the maximum total sleep utility Goneril can achieve?

Input

Line 1: Two space-separated integers: N and B

Lines 2…N+1: Line i+1 contains a single integer, U_i, between 0 and 200,000 inclusive

Output

The day is divided into 5 periods, with utilities 2, 0, 3, 1, 4 in that order. Goneril must pick 3 periods.

Sample Input

5 3
2
0
3
1
4

Sample Output

6

Hint

INPUT DETAILS:

The day is divided into 5 periods, with utilities 2, 0, 3, 1, 4 in that order. Goneril must pick 3 periods.

OUTPUT DETAILS:

Goneril can get total utility 6 by being in bed during periods 4, 5, and 1, with utilities 0 [getting to sleep], 4, and 2 respectively.

题意:

有一只牛要休息m个时间段,现在有n个时间段可以供选择,一个时间段有一个睡眠价值,这m个时间段可以连续也可以不连续,每次睡觉的第一个时间段时不获得睡眠价值的,这个牛可以从第一天的晚上睡到第二天的早上,也就是第n个时间段是连着第一个时间段的。问这个牛可以获得的最大的睡眠价值是多少?

环形dp:把问题用两部分覆盖,于是把环形转化成两次线性DP。

题解:

在这里插入图片描述

AC代码

#include<iostream>
#include<cstring>
#include<algorithm> 
using namespace std;
const int maxn=4010;
int dp[maxn][2],u[maxn];
int n,b;
void DP(){
	for(int i=2;i<=n;i++){
		for(int j=b;j;j--){
			dp[j][0]=max(dp[j][0],dp[j][1]);
			dp[j][1]=max(dp[j-1][0],dp[j-1][1]+u[i]);
		}
	}
}
int main(){
	//int n,b;
	cin>>n>>b;
	for(int i=1;i<=n;i++) cin>>u[i];
	 //fill(dp[0],dp[0]+10*10,-1);
	 memset(dp,0xcf,sizeof(dp));
	dp[0][0]=dp[1][1]=0;
	DP();
	int ans=0;
	ans=max(ans,max(dp[b][0],dp[b][1]));
	//fill(dp+1,dp+n+1,inf);
	memset(dp,0xcf,sizeof(dp));
	dp[1][1]=u[1];
	DP();
	ans=max(ans,dp[b][1]);
	cout<<ans<<endl;
	return 0;
}

参考博客:blog.csdn.net/qq_41958841/article/details/82885695

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值