2017百度之星资格赛 1003 度度熊与邪恶大魔王(完全背包)

度度熊与邪恶大魔王

Accepts: 2016
Submissions: 12307
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
传送门: bestcoder

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

Sample Output

8 16

Aceppted代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
Problem:度度熊与邪恶大魔王
Author:QiZhao
Data:2017-08-05
Description:DP,完全背包
Copyright 2017 QiZhao. All rights reserved.
*/
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1020;
const ll INF=0x3f3f3f3f;

ll num[maxn][12];//防御值为j,生命值为i的怪物的个数
ll dp[1020][15];//对于生命值为i,防御值为j的怪物所消耗的最小水晶数
struct skill
{
ll hit;
ll price;
} a[maxn];
ll best[maxn];//攻击力为i时,消耗的最少水晶数。

ll min(ll a,ll b)
{
if(a>b)
return b;
else
return a;
}

void complete_packet(int k, int p)//p为攻击力,k为消耗水晶数
{
for (int b = 0; b <= 10; ++b)
{
if (b >= p)
{
continue;
}
else
{
int d = p - b;
//血量小于攻击
for (int a = 1; a <= d; ++a)
{
dp[a][b] = min(dp[a][b], k);
}
//血量大于攻击
for (int a = d + 1; a <= 1000; ++a)
{
dp[a][b] = min(dp[a][b], dp[a - d][b] + k);
}
}
}
}

int main()
{
cin.sync_with_stdio(false);
ll n, m;
ll x, y;
ll /*max_hp = -0xffff,*/ max_def = -INF, max_hit = -INF;
while(cin >> n >> m)
{
max_def = -INF, max_hit = -INF;
memset(num, 0, sizeof(num));
memset(a, 0, sizeof(a));
memset(best, -1, sizeof(best));
memset(dp, 0, sizeof(dp));
for(ll i = 0; i < n; i++)
{
cin >> x >> y;
num[x][y]++;
//if(x >= max_hp)
//max_hp = x;
if(y >= max_def)
max_def = y;
}
ll flag = 0;
for(ll i = 0; i < m; i++)
{
cin >> x >> y;
if(best[y] == -1)
{
a[flag].hit = y;
a[flag].price = x;
best[y] = x;
if(a[flag].hit > max_hit)
max_hit = a[flag].hit;
flag++;
}
else
{
if(x < best[y])
best[y] = x;
}
}
ll ans = 0;
ll temp = 0; //记录已处理怪物个数,优化时间
if(max_def >= max_hit)
cout << "-1" << endl;
else
{
for (int i = 0; i <= 1010; ++i)//初始化DP
{
for (int j = 0; j <= 10; ++j)
{
if (i == 0)
{
dp[i][j] = 0;
}
else
{
dp[i][j] = INF;
}
}
}
for(int i=0;i<flag;i++)
complete_packet(best[a[i].hit],a[i].hit);
for(ll i = 0; i < 1002; i++)
{
if(temp == n)//优化时间
break;
for(ll j = 0; j < 12; j++)
{
if(num[i][j] != 0)
{
temp += num[i][j];
ans += dp[i][j]*num[i][j];
}
}
}
cout << ans << endl;
}
}
return 0;
}
您的支持是我继续创作最大的动力!

欢迎关注我的其它发布渠道