题目描述
小Q打算穿越怪兽谷。他不会打怪,但是他有钱(笑~*´∀`)。他知道,只要给怪兽一定的金币,怪兽就会一直护送着他出谷。
在谷中,他会依次遇见N之怪兽,每只怪兽都有自己的武力值和要“贿赂”它所需的金币数。如果小Q没有“贿赂”某只怪兽,而这只怪兽“武力值”又大于护送他的怪兽武力值之和,这只怪兽就会攻击他。
小Q想知道,想要成功穿越怪兽谷而不被攻击,他最少要准备多少金币。
输入描述
第一行输入一个整数N,代表怪兽的只数
第二行输入N个整数d1,d2,…,dn,代表武力值
第三行输入N个整数p1,p2,…,pn,代表收买N只怪兽所需的金币数
(1≤N≤50,1≤d1,d2,…,dn≤1012,1≤p1,p2,…,pn≤2)
输出描述
输出一个整数,代表所需的最小金币数
示例1
输入
3
8 5 10
1 1 2
输出
2
示例2
输入
4
1 2 4 8
1 2 1 2
输出
6
题目分析
这道题读完,我的第一反应是,真简单,不就是设置一个变量nowD,记录小Q当前的武力值之和,然后进行N次循环,依次遭遇怪兽。每遇到一个怪兽判断一下,当前的武力值之和nowD是否小于碰到怪兽的武力值,如果小于则花钱贿赂,否则直接通过。最后输出总共花费的金币数。
结果当然是我太傻太天真,作为鹅厂的算法题,怎么可能这么简单。
对于示例2而言,由于从头到尾,nowD都会小于怪兽的武力值,所以每次都需要购买,通过上面做法,结果输出正确。但是对于示例1而言,当遭遇第2个怪兽时,按上面做法,由于nowD为8大于怪兽武力值5,所以选择不贿赂,但遭遇第3个怪兽时,则必须贿赂通过,则输出结果为1+2=3,并不是示例1输出的答案2。示例1正确的走法是,贿赂第一和第二个怪兽,碰到第三个怪兽nowD=13大于10,成功出谷,输出2。
不想听我罗嗦,想直接看做法请看下面
解法
采用递归的方法解决。
由于每次遇到怪兽,先不论打不打过,都有两种选择,贿赂与不贿赂,即会导致出现两种路线。于是通过递归调用,生成2N-1条路线。一次递归方法中,分别计算贿赂与不贿赂这两条路线的花费金币数,比较后返回花费最少的路线所需的金币数。由于此方法类似于穷举算法,为了减少计算量,走到某一步时,若怪兽武力值大于nowP时,直接截断返回整数的最大值Integer.MAX_VALUE,这样可以便于比较输出最小值。最后递归的结束条件是,当走过最后一直怪兽时返回最终的花费。
语言表达能力有限,觉得听不懂的小伙伴可以看下图或者直接看代码。
解法示例图
以示例1为例
示例代码(java)
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();//挂
long[] D = new long[N];//怪兽武力值数组
int[] P = new int[N];//怪兽贿赂所需金币数组
//循环录入
for(int i = 0 ; i < N; i ++) {
D[i] = sc.nextLong();
}
for(int i = 0 ; i < N; i ++) {
P[i] = sc.nextInt();
}
//开始调用递归方法,起始位置从0开始
//由于初始无武力值,因此默认贿赂第一支怪兽
int result = next(0,N,D,P,D[0],P[0]);
System.out.println(result);
}
/**
* index 当前位置
* end 结束位置
* D[] 武力值数组
* P[] 金币数组
* nowD 当前武力值之和
* sumP 总共花费金币数
*/
public static int next(int index,int end
,long D[],int P[]
,long nowD,int sumP) {
//如果当前怪兽武力值大于nowD
//直接截断返回整数最大值(便于比较大小),减少测试路线数量
if(D[index] > nowD) {
return Integer.MAX_VALUE;
}
index ++;
//如果走到最后位置,则返回sunP
if(index == end) {
return sumP;
}
//第一条路线,默认贿赂怪兽,递归调用下一步
int sumP1 = next(index,end,D,P,nowD+D[index],sumP+P[index]);
//第二条路线,默认不贿赂怪兽,递归调用下一步
int sumP2 = next(index,end,D,P,nowD,sumP);
//结果返回两条路线中花钱最少的sumP
return sumP1<sumP2?sumP1:sumP2;
}
}