[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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值