題目鏈接: 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;
}