CF-div3-627-E. Sleeping Schedule| dp

思路

状态转移方程

dp[i][j] 表示第i个位置,在时间为j下的 好睡眠次数
dp[i-1][j] 可以推出 dp[i][j+a[i]] 和 dp[i][j+a[i]-1];

l,r时间段内:dp[i][u] = max(dp[i][u],dp[i-1][j] + 1); // u表示 j-a[i] 或者 j-(a[i]+1)
非l,r时间内:dp[i][u] = max(dp[i][u],dp[i-1][j]);

另外dp[i][j]初值设置为-1,因为前一时刻dp[i-1][j]下在j时刻可能未醒来,即前一个状态未到达,那么当前状态也不可能到达了

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 2100;
int a[maxn];
int dp[maxn][maxn];
int n,h,l,r;

int main(){
	cin>>n>>h>>l>>r;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	//判断是否经历过dp[i-1][j] 没经历过肯定不可退出下一阶段 
	memset(dp,-1,sizeof dp); //表示当前状态下未醒来:有状态是无法达到的 设置初态为-1未到达过  
	dp[0][0] = 0; //只能由初状态得来 
	for(int i=1;i<=n;i++){
		for(int j=0;j<h;j++){
			if(dp[i-1][j] == -1) continue; //没到达过i-1,j肯定不可推当当前 
			int u = (j + a[i])%h;
			int v = (j + a[i] - 1)%h;
			if(u>=l && u<=r){
				dp[i][u] = max(dp[i][u],dp[i-1][j] + 1);
			}else dp[i][u] = max(dp[i][u],dp[i-1][j]);
			if(v>=l && v<=r){
				dp[i][v] = max(dp[i][v],dp[i-1][j] + 1);
			}else dp[i][v] = max(dp[i][v],dp[i-1][j]);
		}
	}
	int ans = 0;
	for(int j=0;j<h;j++){
		ans = max(ans,dp[n][j]);
	}
	cout<<ans;
} 

猜你喜欢

转载自www.cnblogs.com/fisherss/p/12724820.html