codeforces gym #101161H

题目链接:

http://codeforces.com/gym/101161/attachments

题意:

总共有n瓶药可供选择

每瓶药可以增加$e_i$点体力,和$p_i$点毒性

每分钟消耗1点毒性,毒性不能大于99,体力不能小于0大于100

击败一只怪物消耗$k$点体力,花费$m$分钟

计算不最大击败怪物的数量

数据范围:

$1leq nleq 8$

分析: 

定义$dp[i][j][k]$为药物状态为$i$,体力为$j$,毒性为$k$的最大击败数

初始化$dp[0][100][0]=0$

对于每个$dp[i][j][k]$,可以选择击败一只怪物不喝药,或者在$i$状态下,击败一只怪物并且喝一瓶没有喝过的药

ac代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 1e5+100;
int dp[(1<<8)+7][101][101];
int e[9],p[9],k,m;
int main()
{
    int T,d,m,n;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&d,&m);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&e[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&p[i]);
        int len=(1<<n);
        for(int i=0;i<len;i++)
            for(int j=0;j<=100;j++)
                for(int k=0;k<=100;k++)
                    dp[i][j][k]=-1e9;
        dp[0][100][0]=0;
        for(int i=0;i<len;i++){
            for(int j=100;j>=d+1;j--){
                  for(int k=0;k<=99;k++){
                        dp[i][j-d][max(0,k-m)]=
                        max(dp[i][j][k]+1,dp[i][j-d][max(0,k-m)]);
                        for(int f=1;f<=n;f++){
                            if(((1<<(f-1))&i)==0){
                                if(max(0,k-m)+p[f]<=99)
                                dp[i+(1<<(f-1))][min(100,j-d+e[f])][max(0,k-m)+p[f]]
                                =max(dp[i+(1<<(f-1))][min(100,j-d+e[f])][max(0,k-m)+p[f]],
                                dp[i][j][k]+1);
                            }
                        }
                  }
            }
        }
        int ans=0;
        for(int i=0;i<len;i++)
            for(int j=0;j<=100;j++)
                for(int k=0;k<=99;k++)
                    ans=max(ans,dp[i][j][k]);
        printf("%d
",ans);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/carcar/p/11498731.html