[dp] AIZU 2156 Magic Slayer

题目链接:

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2156

Magic Slayer

Time Limit : 8 sec, Memory Limit : 65536 KB

Problem B: Magic Slayer

You are in a fantasy monster-ridden world. You are a slayer fighting against the monsters with magic spells.

The monsters have hit points for each, which represent their vitality. You can decrease their hit points by your magic spells: each spell gives certain points of damage, by which monsters lose their hit points, to either one monster or all monsters in front of you (depending on the spell). Monsters are defeated when their hit points decrease to less than or equal to zero. On the other hand, each spell may consume a certain amount of yourmagic power. Since your magic power is limited, you want to defeat monsters using the power as little as possible.

Write a program for this purpose.

Input

The input consists of multiple datasets. Each dataset has the following format:

N
HP
1
HP2
...
HPN
M
Name
1 MP1 Target1 Damage1
Name2 MP2 Target2 Damage2
...
NameM MPM TargetM DamageM

N is the number of monsters in front of you (1 ≤ N ≤ 100); HPi is the hit points of the i-th monster (1 ≤ HPi ≤ 100000); M is the number of available magic spells (1 ≤ M ≤ 100); Namej is the name of the j-th spell, consisting of up to 16 uppercase and lowercase letters; MPj is the amount of magic power consumed by the j-th spell (0 ≤ MPj ≤ 99); Targetj is either "Single" or "All", where these indicate the j-th magic gives damage just to a single monster or to all monsters respectively; Damagej is the amount of damage (per monster in case of "All") made by the j-th magic (0 ≤ Damagej ≤ 999999).

All the numbers in the input are integers. There is at least one spell that gives non-zero damage to monsters.

The last dataset is followed by a line containing one zero. This line is not a part of any dataset and should not be processed.

Output

For each dataset, Print in a line the minimum amount of magic power consumed to defeat all the monsters in the input.

Sample Input

3
8000 15000 30000
3
Flare 45 Single 8000
Meteor 62 All 6000
Ultimate 80 All 9999
0

Output for the Sample Input

232
Source: ACM-ICPC Japan Alumni Group Summer Camp 2009 , Day 2, Tokyo, Japan, 2009-09-19 
http://acm-icpc.aitea.net/

题目意思:

有n个怪兽,每个怪兽有个攻击分数hpi,有m种武器,每种武器可以攻击单个怪兽或者所有怪兽,每种武器有一个消耗值和攻击值,求把所有怪兽打打掉需要消耗最小能耗值。

解题思路:

dp.

dp[0][i]:表示当消耗的能量为i时,使用all对每个怪物所造成的伤害的最大值

dp[1][i]:表示当消耗的能量为i时,使用single对单个怪物造成的最大的伤害
vector<pair<int,int> >myv[2]; //表示消耗的能量和能造成的伤害

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<utility>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007

using namespace std;

#define Maxn 110000

int dp[2][Maxn]; //dp[0][i]:表示当消耗的能量为i时,使用all对每个怪物所造成的伤害的最大值
//dp[1][i]:表示当消耗的能量为i时,使用single对单个怪物造成的最大的伤害
vector<pair<int,int> >myv[2]; //表示消耗的能量和能造成的伤害
int n,m,hp[110];
char save[110];

int main()
{

   while(cin>>n)
   {
       if(!n)
            break;
       memset(dp,0,sizeof(dp));
       myv[0].clear();
       myv[1].clear();

       for(int i=1;i<=n;i++)
            scanf("%d",&hp[i]);
       scanf("%d",&m);
       bool flag=false;

       while(m--)
       {
           int en,h;
           scanf("%s%d%s%d",save,&en,save,&h);
           myv[*save=='S'].push_back(make_pair(en,h));
           flag|=(en==0&&h);
       }
       if(flag)
       {
           printf("0\n");
           continue;
       }
       for(int i=0;i<2;i++)
       {
           for(int j=0;j<myv[i].size();j++)
           {
               //printf("i:%d j:%d %d %d\n",i,j,myv[i][j].first,myv[i][j].second);
              // system("pause");
               for(int k=myv[i][j].first;k<=100000;k++)
                   dp[i][k]=max(dp[i][k],dp[i][k-myv[i][j].first]+myv[i][j].second);
               //printf("i:%d k:%d %d\n",i,142,dp[i][142]);

           }
       }

       LL ans=(1LL<<62);

       for(int i=0;i<ans;i++)
       {
           LL temp=i;    //枚举需要的使用的all的总值 

           for(int j=1;j<=n;j++)  //求出最少的sigle总值
           {
               temp+=lower_bound(dp[1],dp[2],hp[j]-dp[0][i])-dp[1];
               //printf("temp:%lld\n",temp);
               //system("pause");
           }

          //printf("i:%d %lld\n",i,temp);
           ans=min(ans,temp); //不断减少范围
           //printf("%lld\n",ans);
          // system("pause");
       }

       printf("%lld\n",ans);

   }
   return 0;
}




你可能感兴趣的:([dp] AIZU 2156 Magic Slayer)