ZOJ 3718 Diablo II

題意:K個技能,第i個技能滿級Bi,加1級攻擊力加Ci,加滿後再額外增加Di攻擊力。N件裝備,第i件裝備加Ai的攻擊力,穿上它後會提升一些技能的等級1級(裝備提升的等級不疊加)。現有X個技能點,Y個裝備槽,問最大攻擊力。(K<=7,N<=100)

題解:技能點最後再加,先穿裝備,用二進制位壓縮代表一個技能是否被裝備提升,那麼dp[mask][num]代表穿上num個裝備,對mask這些技能提升一級的最大攻擊力。然後對每個mask,2^k枚舉是否把一個技能加滿,然後對技能按照Ci排序(不能加滿的話自然加Ci最大的),把沒加滿的技能用剩餘技能點去加。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define PB push_back
using namespace std;
const int Lim=300,N=105;
int dp[Lim][N],sk_num,eq_num,sk_p,eq_p,limit;
struct Skill{
    int b,c,d;
    void read(){
        scanf("%d%d%d",&b,&c,&d);
    }
}sk[8];
struct Equip{
    int c,mas;
    void read(){
        int num;
        scanf("%d%d",&c,&num);
        mas=0;
        for(int i=0,tp;i<num;i++){
            scanf("%d",&tp);
            mas|=1<<(tp-1);
        }
    }
}eq[N];
int cnt[8],ans,idx[8];
void dfs(int k,int res,int p){
    if(k==sk_num){
        for(int i=0;i<sk_num;i++){
            int id=idx[i];
            if(cnt[id]==sk[id].b)res+=sk[id].d+cnt[id]*sk[id].c;
            else if(p>=sk[id].b-cnt[id]){
                res+=sk[id].b*sk[id].c+sk[id].d;
                p-=sk[id].b-cnt[id];
            }
            else{
                res+=(p+cnt[id])*sk[id].c;
                p=0;
            }
        }
        ans=max(ans,res);
    }
    else{
        int tp=cnt[k];
        dfs(k+1,res,p);
        if(p>=sk[k].b-tp){
            cnt[k]=sk[k].b;
            dfs(k+1,res,p-sk[k].b+tp);
            cnt[k]=tp;
        }
    }
}
void getans(int mask,int res){
    memset(cnt,0,sizeof(cnt));
    for(int i=0;i<sk_num;i++)
        if((1<<i)&mask)cnt[i]++;
    dfs(0,res,sk_p);
}
bool comp(int a,int b){
    return sk[a].c>sk[b].c;
}
int main(){
    //freopen("C.in","r",stdin);
    while(scanf("%d%d",&sk_num,&eq_num)!=EOF){
        for(int i=0;i<sk_num;i++)sk[i].read();
        for(int i=0;i<eq_num;i++)eq[i].read();
        for(int i=0;i<sk_num;i++)idx[i]=i;
        sort(idx,idx+sk_num,comp);
        scanf("%d%d",&sk_p,&eq_p);
        memset(dp,-1,sizeof(dp));
        dp[0][0]=0;
        limit=1<<sk_num;
        eq_p=min(eq_p,eq_num);
        for(int k=0;k<eq_num;k++){
            for(int j=eq_p-1;j>=0;j--){
                for(int i=0;i<limit;i++){
                    if(dp[i][j]!=-1){
                        int mas=i|eq[k].mas;
                        dp[mas][j+1]=max(dp[mas][j+1],dp[i][j]+eq[k].c);
                    }
                }
            }
        }
        ans=0;
        for(int i=0;i<limit;i++){
            if(dp[i][eq_p]!=-1)getans(i,dp[i][eq_p]);
        }
        printf("%d\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章