ZOJ 3741 魔禁 dp

题意:

一个人等级为L , 与n个人对打(当自己等级高于或者和对方相同时自己胜利)

第二行输入n个人的等级

有一个技能可以暂时提升等级(使用后x天内提升一级,技能效果过后y天内进入虚弱等级变为0,并且不能使用技能。再过y天恢复到原先等级)

与n个人从第一天开始按顺序每天与一个人对打一次,问:最多的胜利次数。

(注意:等级5 和等级6 无法使用该技能)

 

思路:

三维dp

注意0代表的含义。

 

 

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 101
#define ll int
ll L, n, x, y;
ll dp[N][2][N], non[N], a[N];
// dp[i][0][j]表示第i天 使用了升级技能后的第j天 的最大值 j=0表示这一天不升级的最大值
// dp[i][1][j]表示第i天 处于虚弱状态的第j天的最大值      j=0表示刚用完技能还没开始休息
int main(){
	ll i, j;
	while(~scanf("%d%d%d%d",&L,&n,&x,&y)){
		for(i=1;i<=n;i++)scanf("%d",&a[i]);
		memset(non, 0, sizeof(non));
		memset(dp, 0, sizeof(dp));
		
		for(i=1;i<=n;i++)non[i] = (L>=a[i]) + non[i-1];
		if(L==5){printf("%d\n", non[n]);continue;}

		for(i=1;i<=n;i++)
		{
			dp[i][0][0] = non[i]; //不变身
			dp[i][0][0] = max(dp[i][0][0], dp[i-1][1][y]+(L>=a[i]));
			dp[i][0][0] = max(dp[i][0][0], dp[i-1][0][0]+(L>=a[i]));

			dp[i][0][1] = dp[i][0][0] - (L>=a[i]) + (L+1>=a[i]);
			for(j = 2; j <= x; j++)dp[i][0][j] = dp[i-1][0][j-1]+(L+1>=a[i]);
			if(i>=x)dp[i][1][0] = dp[i][0][x];
			for(j=1;j<=y;j++)dp[i][1][j] = dp[i-1][1][j-1]+(0>=a[i]);
		}
		ll ans = 0;
		for(j=0;j<=x;j++)ans = max(ans, dp[n][0][j]);
		for(j=1;j<=y;j++)ans = max(ans, dp[n][1][j]);
		printf("%d\n",ans);
	}
	return 0;
}
/*
3 6 1 2
1 3 4 5 6 4

6 6 1 2
1 3 4 5 6 4

0 6 1 100
0 0 0 0 0 0

1 4 1 1
1 0 1 0
0 4 1 1
1 1 0 1

0 6 1 2
1 0 1 0 1 1

0 6 1 1
1 2 1 0 1 0

3 10 2 2
1 2 4 4 5 0 5 3 4 1

3 10 2 0
1 2 4 4 5 0 5 3 4 1

3 10 0 2
4 4 4 4 4 4 4 4 4 4

3 10 1 2
4 4 4 4 4 4 4 4 4 4

3 10 1 0
4 4 4 4 4 4 4 4 4 4

3 10 0 0
4 4 4 4 4 4 4 4 4 4

5 1 1 0
6

*/


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值