贪心法基本概念
贪心法就是遵循某种规则,不断贪心地选取当前最优策略。
硬币问题
题目:
思路:
import java.util.Scanner;
public class lanqiao1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int [] cnts = new int[6];
for(int i=0;i<6;i++)
cnts[i] = sc.nextInt();
int A = sc.nextInt();
int res = f(cnts,5,A);
System.out.print(res);
}
static int []cooon={1,5,10,50,100,500};
private static int f(int[] cnts, int i,int A) {
if( A <=0) return 0;
if(i == 0) return A;
int coinValue = A/cooon[i];
int t = Math.min(cnts[i],coinValue);
System.out.println(t+"*"+cooon[i]);
return t+f(cnts,i-1,A-t*cooon[i]);
}
}
快速渡河
题目:
每个人过河都有自己的过河时间,有n个人想过河,但只有一只小船,最多只能装2个人,每一次过河,过河时间为用时最多的那人过河时间,如果还有人没有过河,那么过去一个用时最少的送回船。问n人过河最少要多少时间。
思路:
寻找渡河策略,设4人的渡河时间a b c d (a<b<c<d)。
策略一:
最快的和次快的过去,最快的返程;最快的和第三快的过去,最快的返程…
形象化描述为:
策略二:
最快的和最慢的过去,最快的返程;最快的和次慢的过去,最快的返程…
形象化描述为:
3b+a+d 与 2a+b+c+d 比较大小,即 2b 与 a+c 比较;这个无法判断,因为取决于具体的数字,所以只要在两策略中取min最小即可。
import java.util.Arrays;
import java.util.Scanner;
public class lanqiao1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt(); //几组
for(int i=0;i<T;i++){
int n = sc.nextInt();
int []speed= new int[n];
for(int j=0;j<n;j++){
speed[j] = sc.nextInt();
}
Arrays.sort(speed);
f(n,speed);
}
}
private static void f(int n, int[] speed) {
int left = n;
int ans=0;
while(left>0){
if(left == 1){
ans+=speed[0];
break;
}
else if(left == 2){
ans+=speed[1];
break;
}
else if(left == 3){
ans+=speed[2]+speed[1]+speed[0];
}
else{
int s1 = speed[1]+speed[0]+speed[left-1]+speed[1];
int s2 = speed[left-1]+speed[0]+speed[left-2]+speed[0];
ans += Math.min(s1,s2);
left-=2;
}
}
System.out.println(ans);
}
}
小结
在贪心算法中,想找到正确的解题策略往往要通过猜
+证明
(多用反证)。