● 本题解会有详细的分析,适合初学者阅读

原题

Problem Description

There is a mountain near yifenfei’s hometown. On the mountain lived a big monster. As a hero in hometown, yifenfei wants to kill it.
Now we know yifenfei have n spells, and the monster have m HP, when HP <= 0 meaning monster be killed. Yifenfei’s spells have different effect if used in different time. now tell you each spells’s effects , expressed (A ,M). A show the spell can cost A HP to monster in the common time. M show that when the monster’s HP <= M, using this spell can get double effect.

Input

The input contains multiple test cases.
Each test case include, first two integers n, m (2<n<10, 1<m<10^7), express how many spells yifenfei has.
Next n line , each line express one spell. (Ai, Mi).(0<Ai,Mi<=m).

Output

For each test case output one integer that how many spells yifenfei should use at least. If yifenfei can not kill the monster output -1.

Sample Input

3 100
10 20
45 89
5 40

3 100
10 20
45 90
5 40

3 100
10 20
45 84
5 40

Sample Output

3
2
-1

题目翻译

Problem Description

现在我们知道大佬有n个法术,怪物有m个生命值,当生命值<=0时意味着怪物被杀死。大佬的咒语在不同时间使用效果不同。现在告诉你每一个法术的效果,表示为(A,M)。在普通时间,该法术可以降低怪物一点生命。显示当怪物的血量<=M时,使用此法术可获得双倍效果。

Input

输入包含多个测试用例。
每个测试用例包括,前两个整数n,m(2<n<10,1<m<10^7),表示大佬有多少咒语。
下一行,每行表示一个咒语。(Ai,Mi)。(0<Ai,Mi<=m)。

Output

对于每个测试用例,输出一个整数,表示大佬最少应该使用多少个咒语。如果大佬不能杀死怪物输出-1。

题目分析

水题,数据规模小的可怜,暴力搜索解决。

思路很简单,我们把一次递归理解成对怪兽施法一次,当怪兽GG掉的事后我们结束施法,每次施法时,我们身上的计数器都会+1,每个法术只能使用一次,用完就冷却,如果本场战斗结束,那么冷却的法术恢复,继续下一轮战斗。每场战斗结束后更新一下使用技能数的最小值。

将这个通俗的说法翻译成生肉:以怪物的hp作为dfs的状态量,当hp <= 0时怪兽死亡,搜索结束,更新最小值并出栈函数;如果没死,就从技能列表中找能用的技能,同时注意技能造成的伤害在不同条件下不同,找到合法技能就递归向下继续搜到怪兽死亡为止

这里一个基本剪枝:如果当前使用的技能数已经超越历史最小技能数了,不管这场战斗能不能赢,已经没有继续战斗的必要了,返回即可

AC Code

#include <bits/stdc++.h>
using namespace std;

pair<int, int> g[20];
bool vis[20];
int minn, n, m;

void dfs(int hp, int cnt){
if(cnt > minn || cnt > n) return;
if(cnt < minn && hp <= 0){
minn = cnt; return;
}
for(int i = 0; i < n; i++){
if(!vis[i]){
vis[i] = true;
if(hp <= g[i].second) dfs(hp - g[i].first * 2, cnt + 1);
else dfs(hp - g[i].first, cnt + 1);
vis[i] = false;
}
}
}

int main(){
while(cin >> n >> m){
for(int i = 0; i < n; i++) cin >> g[i].first >> g[i].second;
for(int i = 0; i < 20; i++) vis[i] = false;
minn = INT_MAX;
dfs(m, 0);
if(minn >= 20) cout << -1 << endl;
else cout << minn << endl;
}
return 0;
}