F. Magic Will Save the World(DP)

Problem - F - Codeforces

F. Magic Will Save the World(DP)_第1张图片

黑暗势力的传送门在世界边界打开了,现在整个世界都面临着可怕的威胁。为了关闭传送门并拯救世界,你需要一个接一个地击败n个从传送门中出现的怪物。

只有女巫Vika能够应对这个威胁。她有两个魔法力量——水之魔法和火之魔法。Vika每秒可以生成w单位的水魔法能量和f单位的火魔法能量。她需要能量来施放法术。初始时,Vika没有水魔法和火魔法能量。

从传送门中出现的每个怪物都有自己的力量,用一个正整数表示。为了击败第i个力量为si的怪物,Vika需要施放一个至少具有相同力量的水系或火系法术。换句话说,Vika可以花费至少si单位的水魔法能量来施放水系法术,或者至少si单位的火魔法能量来施放火系法术。

Vika可以立即创建和施放法术。只要她有足够的能量,她可以每秒施放无数次法术。

女巫希望尽快拯救世界,因此告诉她需要多少时间。

输入

每个测试包含多个测试用例。每个测试的第一行包含一个整数t(1≤t≤100),表示测试用例的数量。接下来是每个测试用例的描述。

每个测试用例的第一行包含两个整数w和f(1≤w,f≤109),表示Vika每秒可以生成的水魔法和火魔法能量。

每个测试用例的第二行包含一个整数n(1≤n≤100),表示怪物的数量。

每个测试用例的第三行包含n个整数s1,s2,s3,…,sn(1≤si≤104),表示怪物的力量。

保证所有测试用例中n的总和不超过100。

输出

对于每个测试用例,输出一个整数,表示Vika击败所有怪物所需的最短时间(秒)。

Example

Input

Copy

 
  

4

2 3

3

2 6 7

37 58

1

93

190 90

2

23 97

13 4

4

10 10 2 45

Output

Copy

3
2
1
5

题解:

我们可以dp求出在魔法为i时,是否可以全部利用为i的魔法

只有这种情况才能求出最优解,

总共需要的魔法量为sum为怪物生命值的总和

根据数据范围,sum最大为1e6

当i = 0~1e6,并且此时魔法可以完全被利用

会有两种情况,

f利用i,w利用sum - i 两者所用t取最大

同理或者w利用i,f利用sum - i

所有最优情况再取最小即可

#include
#include
using namespace std;
#define int long long
typedef pair PII;
const int N = 5e5 + 10;
int a[N];
int dp[N*2];
void solve()
{
	int n,w,f;
	cin >> w >> f >> n;
	int sum = 0;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i];
		sum += a[i];
	}
	
	memset(dp,0,sizeof dp);
	dp[0] = 1;
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1e6;j >= a[i];j --)
		{
			dp[j] |= dp[j - a[i]];
		}
	}
	int ans = 1e9;
	for(int i = 0;i <= 1e6;i++)
	{
		if(dp[i])
		{
			ans = min(ans,max((i + w - 1)/w,(sum - i + f - 1)/f));
			ans = min(ans,max((i + f - 1)/f,(sum - i + w - 1)/w));
		}
	}
	cout << ans <<"\n";
} 
//
signed main()
{
	int t = 1;
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t ;	
	while(t--)
	{
		solve();
	}
}
//70 30 90
//100 90

你可能感兴趣的:(DP)