度度熊与邪恶大魔王(dp)打boss2

度度熊与邪恶大魔王

 
 Accepts: 3666
 
 Submissions: 22474
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 32768/32768 K (Java/Others)
Problem Description

度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗起来。

邪恶大魔王的麾下有n个怪兽,每个怪兽有a[i]的生命值,以及b[i]的防御力。

度度熊一共拥有m种攻击方式,第i种攻击方式,需要消耗k[i]的晶石,造成p[i]点伤害。

当然,如果度度熊使用第i个技能打在第j个怪兽上面的话,会使得第j个怪兽的生命值减少p[i]-b[j],当然如果伤害小于防御,那么攻击就不会奏效。

如果怪兽的生命值降为0或以下,那么怪兽就会被消灭。

当然每个技能都可以使用无限次。

请问度度熊最少携带多少晶石,就可以消灭所有的怪兽。

Input

本题包含若干组测试数据。

第一行两个整数n,m,表示有n个怪兽,m种技能。

接下来n行,每行两个整数,a[i],b[i],分别表示怪兽的生命值和防御力。

再接下来m行,每行两个整数k[i]和p[i],分别表示技能的消耗晶石数目和技能的伤害值。

数据范围:

1<=n<=100000

1<=m<=1000

1<=a[i]<=1000

0<=b[i]<=10

0<=k[i]<=100000

0<=p[i]<=1000

Output

对于每组测试数据,输出最小的晶石消耗数量,如果不能击败所有的怪兽,输出-1

Sample Input
1 2
3 5
7 10
6 8
1 2
3 5
10 7
8 6
Sample Output
6
18

#include<bits/stdc++.h>
#define MAXN 1050


using namespace std;
int n,m;
long long int dp[MAXN][11]={0};//把防御值为j的怪物,生命值打掉i需要消耗的最少的水晶数。
long long int num[MAXN][11]={0};//num[i][j]生命值为i,防御为j的怪物个数
int spend[MAXN],hit[MAXN];
long long int ans=0;
int best[MAXN];
struct SKILL
{
    int hit;
    int spend;
}a[MAXN];
/*bool my_cmp(SKILL x,SKILL y)
{
    if(x.spend!=y.spend)
    return x.spend>y.spend;
}*/

int main()
{
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            ans=0;
            memset(num,0,sizeof(num));
            memset(dp,0,sizeof(dp));
            memset(best,0,sizeof(best));

            int max_hit=0,max_def=0,max_hp=0;int lx,ly;
            for(int i=0;i<n;i++)
            {
                scanf("%d%d",&lx,&ly);
                num[lx][ly]++;
                if(max_def<ly)max_def=ly;
                if(max_hp<lx)max_hp=lx;
            }
            int l_num=0;
            for(int i=0;i<m;i++)
            {
                scanf("%d%d",&lx,&ly);
                if(best[ly]!=0&&best[ly]<=lx)continue;
                best[ly]=lx;
                a[l_num].spend=lx;a[l_num].hit=ly;
                if(a[l_num].hit>max_hit)
                {
                    max_hit=a[l_num].hit;
                }
                l_num++;
            }
            m=l_num;
            if(max_hit<=max_def)
            {
                printf("-1\n");
                continue;
            }
            //sort(a,a+m,my_cmp);
            for(int k_def=0;k_def<=10;k_def++)//枚举所有防御力可能
            {
                //int min_cost=1000000,min_cost_num=-1;
                if(k_def!=0)
                    for(int i=0;i<m;i++)
                    {
                        a[i].hit--;
                    }
                /*for(int i=0;i<m;i++)//找到最小花费
                {
                    if(a[i].hit<=0)continue;
                    if(a[i].cost<=min_cost)
                    {
                        min_cost=a[i].cost;
                        min_cost_num=i;
                    }
                }*/
                for(int i=1;i<=max_hp;i++)
                {
                    long long t=-1;
                    for(int j=0;j<m;j++)
                    {
                        if(a[j].hit<=0)continue;
                        if(i-a[j].hit<=0)
                        {
                            if(t==-1||t>a[j].spend)
                            {
                                t=a[j].spend;
                            }
                            continue;
                        }
                        if(t==-1||t>dp[i-a[j].hit][k_def]+a[j].spend)
                        {
                            t=dp[i-a[j].hit][k_def]+a[j].spend;
                        }
                    }
                    dp[i][k_def]=t;
                }
            }
            for(int i=0;i<=max_hp;i++)
            {
                for(int j=0;j<=10;j++)
                {
                    ans+=(dp[i][j]*num[i][j]);
                }
            }
            printf("%I64d\n",ans);
        }

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值