题目链接: http://codeforces.com/gym/101161/attachments
题意:
你在初始状态下有 点能量, 点毒素值,你现在要连续的打小怪兽,打每只小怪兽需要花费你 点能量和 单位时间。你现在有 瓶药水,每瓶药水只能喝一次,并且在打一只小怪兽时最多喝一瓶,每瓶药水有一个增加的能量 和一个毒素增加值 ,你体内的毒素如果大于等于 ,你会立刻死亡,每过单位时间毒素会减少 ,增加后能量不超过 ,毒素减少不低于 ,问你最多能打几只小怪兽。
做法:
表示在喝药状态为 的状态下,你有能量 点,毒素为 时能打小怪兽的最大值, 表示在这个状态下是否吃了药。(因为我们不知道在这个状态下我们打小怪兽的时候是不是已经吃过药了,所以需要一维控制)。
然后根据题意进行转移即可。
代码
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = (int)a;i<=(int)b;i++)
using namespace std;
const int inf=1e9+7;
const int maxn=100005;
const int maxm=(1<<8);
int dp[maxm+5][105][105][2];
//嗑药状态为i 当前体力为j时 毒性为k时 是否吃过药 能打的最多小怪兽数量
int Eng[10],Pot[10],n,K,M;
int main(){
int T; scanf("%d",&T);
while(T--){
scanf("%d%d",&K,&M);
scanf("%d",&n);
rep(i,0,n-1) scanf("%d",&Eng[i]);
rep(i,0,n-1) scanf("%d",&Pot[i]);
for(int i=0;i<=100;i++)
for(int j=0;j<(1<<n);j++)
for(int k=0;k<=100;k++) dp[j][i][k][0]=dp[j][i][k][1]=-inf;
dp[0][100][0][0]=0;
int ans=0;
for(int s=0;s<(1<<n);s++){
for(int i=100;i>=1;i--){
for(int j=99;j>=0;j--){
for(int k=0;k<=1;k++){
if(dp[s][i][j][k]==-inf) continue;
int ni=i-K,nj=max(j-M,0),ns;
if(i>K) {
dp[s][ni][nj][0]=max(dp[s][ni][nj][0],dp[s][i][j][k]+1);
ans=max(ans,dp[s][ni][nj][0]);
}
if(k!=0) continue;
for(int p=0;p<n;p++){
if(s&(1<<p)||j+Pot[p]>=100) continue;
ns=s|(1<<p); ni=min(100,i+Eng[p]); nj=j+Pot[p];
dp[ns][ni][nj][1]=max(dp[ns][ni][nj][1],dp[s][i][j][k]);
ans=max(ans,dp[ns][ni][nj][1]);
}
}
}
}
}
printf("%d\n",ans);
}
return 0;
}