内存限制:128 MB时间限制:1 S标准输入输出
题目描述
自从上次AWM打了整个弹夹的子弹都没有打中一枪后,小明被队友叫去当医疗兵。小明有个癖好,就是只收集医疗包和饮料。假设我们已经知道小明即将被子弹射中的伤害序列,问小明最多能撑到第几颗子弹,即被第几颗子弹射中后,还是活着的(血量大于0就算活着)。一开始小明的血量为满(100),医疗包只能在血量低于70使用,使用后血量会直接恢复到70,饮科可以在任意血量下使用,使用后血量增加30。
输入格式
多组测试数据,首先第一行一个整数T,代表测试数据组数。1≤T≤100。
每组测试数据有a,b,n,代表有a个医疗包。b瓶饮料,n个子弹即将射中小明,接下来有n个数,第i个数xi代表第i颗子弹对小明的伤害。0≤a,b≤100,1≤n,xi≤100,a,b,n,xi均是非负整数。
输出格式
对于每组数据输出一个数c,代表小明最多撑到第c颗子弹。
输入样例 复制
3
1 1 3
20 90 70
0 0 1
100
0 0 2
10 90
输出样例 复制
2
0
1
思路:
动态规划,有七种转移:
-
用1个医疗包
-
用1个医疗包和1个饮料
-
用1个饮料
-
用2个饮料
-
用3个饮料
-
用4个饮料
-
什么都不用
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAX(a,b,c,e,d,f,g) max(a,max(b,max(c,max(d,max(e,max(f,g))))))
#define _INF -0x7fffffff
using namespace std;
int dp[105][105][105];
int que[105];
int n;
int t;
int main()
{
cin>>t;
while(t--)
{
int a,b;
memset(dp,0,sizeof(dp));
memset(que,0,sizeof(que));
scanf("%d%d%d",&a,&b,&n);
for(int i=1;i<=n;++i)
scanf("%d",&que[i]);
for(int i=0;i<=a;++i)
for(int j=0;j<=b;++j)
dp[0][i][j]=100;
int t=0,ans=0;
for(int i=1;i<=n;++i)
{
int c=t;
for(int j=0;j<=a;++j)
{
for(int k=0;k<=b;++k)
{
dp[i][j][k]=MAX(
dp[i-1][j][k]-que[i],
(j>0&&dp[i-1][j-1][k]>0&&dp[i-1][j-1][k]<=70)? 70-que[i]:_INF,
(dp[i-1][j-1][k-1]>0&&j>0&&k>0&&dp[i-1][j-1][k-1]<=70)? 100-que[i]:_INF,
(k>0&&dp[i-1][j][k-1]>0)? (dp[i-1][j][k-1]>70? 100-que[i]:dp[i-1][j][k-1]+30-que[i]):_INF,
(k>1&&dp[i-1][j][k-2]>0)? (dp[i-1][j][k-2]>40? 100-que[i]:dp[i-1][j][k-2]+60-que[i]):_INF,
(k>2&&dp[i-1][j][k-3]>0)? (dp[i-1][j][k-3]>10? 100-que[i]:dp[i-1][j][k-3]+90-que[i]):_INF,
(k>3&&dp[i-1][j][k-4]>0)? (100-que[i]):_INF
);
if(dp[i][j][k]>0)
t++;
}
}
if(c!=t)
ans=max(ans,i);
}
cout<<ans<<endl;
}
return 0;
}