zoj3769(分组背包)

来源:互联网 发布:robotdk编程软件 编辑:程序博客网 时间:2024/05/29 13:31

链接:点击打开链接

题意:有13种装备,每种装备只能选一个,每种装备有一个伤害值和防御值,其中如果选Two-Handed的话就不能选Shield和Weapon,Finger可以选两个。求怎样选择,使得在防御值达最小到m的情况下,伤害总值最大。

代码:

#include <queue>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;char cnt[50][50]={"Head", "Shoulder", "Neck", "Torso", "Hand", "Wrist", "Waist", "Legs", "Feet", "Finger", "Shield", "Weapon", "Two-Handed"};int found(char s[]){    int i;    for(i=0;i<13;i++)    if(strcmp(s,cnt[i])==0)    return i;}struct node{    int x,y;    node(int a,int b){        x=a,y=b;    }};vector<node> G[20];int cmp(vector<node> x,vector<node> y){    return x.size()>y.size();}int dp[305][50005];int main(){    char str[105];    int n,m,i,j,k,t,a,b,tmp,len;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        for(i=0;i<13;i++)        G[i].clear();        for(i=0;i<n;i++){            scanf("%s %d %d",str,&b,&a);            G[found(str)].push_back(node(a,b));        }        tmp=G[9].size();        for(i=0;i<tmp;i++){            for(j=i+1;j<tmp;j++)            G[9].push_back(node(G[9][i].x+G[9][j].x,G[9][i].y+G[9][j].y));        }                                       //将所有finger的情况合并        tmp=G[10].size();        for(i=0;i<tmp;i++){            for(j=0;j<G[11].size();j++)            G[10].push_back(node(G[10][i].x+G[11][j].x,G[10][i].y+G[11][j].y));        }        for(j=0;j<G[11].size();j++)             //把shield和weapon合并        G[10].push_back(node(G[11][j].x,G[11][j].y));        for(j=0;j<G[10].size();j++)             //并且和two-hand合并        G[12].push_back(node(G[10][j].x,G[10][j].y));           G[10].clear(),G[11].clear();        sort(G,G+13,cmp);                       //按照每种武器的数量从大到小排序        memset(dp,-1,sizeof(dp));               //可以快速增加有用的状态        dp[0][0]=0;        for(i=1;i<=13;i++){            len=G[i-1].size();            for(j=0;j<=m;j++){                dp[i][j]=max(dp[i][j],dp[i-1][j]);                if(dp[i-1][j]==-1)                continue;                for(k=0;k<len;k++){             //变成一个分组背包                    tmp=min(m,j+G[i-1][k].x);                    dp[i][tmp]=max(dp[i][tmp],dp[i-1][j]+G[i-1][k].y);                }            }        }        printf("%d\n",dp[13][m]);    }    return 0;}


 

0 0