什么是贪心???
贪心对于刚接触的人来说:贪心??什么鬼?
这里给你两种解释:
1,给你三个妹子做女朋友,第一个有钱,第二个有才,第三个很美,你会选第一个?第二个还是第三个,如果你选的第一个,说明你想在未来自己可以少奋斗30年,如果你选的第二个,说明你这人比较有文化,物以类聚嘛,如果第三个……宅男的梦想啊。当然如果是是我,我当然是把三个都选了,嘿嘿,男人有个三妻四妾算正常吧。别问我为什么,问就是我很贪,贪心的贪,我觉得贪心就是贪,看到啥就贪啥,不会管贪了之后,会有什么道德伦理、贪官落网啥的,这就是贪,就是选当前最优的选择。
2,顾眼前:
遵循某种规则,不断(贪心的)选取当前最优策略,最终找到最优解。
难点:当前最优未必是整体最优
3,官方解释:(点击查看)
贪心案例列表:
- 硬币问题
硬币问题:
有1元、5元、10元、50元、100元、500元的硬币各
c1、c5、c10、c50、c100、c500枚
现在要用这些硬币来支付A元,最少需要多少枚硬币?
假定本题至少存在一种支付方案,
0<=ci<=10^9
0<=A<=10^9
输入:
第一行有六个数字,分别代表从小到大6种面值的硬币个数
第二行为A,代表需要支付的A元
样例:
输入
3 2 1 3 0 2
620
输出:
6
思考:
这题求最少需要多少硬币
这题原解是用的递归,我开始也打算用递归的,可是吧,我做不出来呢,刚好我觉得使用迭代还是不错的呢,故我先用迭代法求解,然后再用递归求解,这题算一题两解吧
迭代法:
import java.util.Scanner;
public class CoinsQuestion {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int value[] = {1, 5, 10, 50, 100, 500};//每个硬币的面值
//接收题目给出的数字
int a[] = new int[6];//每个硬币面值的数量
for(int i = 0; i < 6; i++){
a[i] = sc.nextInt();
}
int n = sc.nextInt();//需要支付的价格
int ans = 0;//ans存储花费的硬币数
for(int i = 5; i >= 0; i--){
//编写一个while循环,用于防止硬币的价格大于需要花费的价格
//PS:总不能你给老板250,老板倒给你250吧
while(value[i]*a[i] > n){
a[i]-=1;
}
//将每次最大的硬币面值乘以它对应的数量(前提就是硬币总面值不会大于需要支付的价格啦)
n = n - value[i]*a[i];
//前面已经说了,ans存储花费的硬币数量
ans += a[i];
//这里做一个提前判断,如果需要支付的价格已经支付完了,那就提前退出循环呗,直接走人
if(n == 0)break;
}
//最后打印存储花费的硬币数
System.out.println(ans);
}
}
迭代法的思路:
思路这东西写多了,等你回头再做的时候,发现还是和没写一样,有个屁用,所以个人觉得这种东西有点难写,不过如果不写,感觉有点……
首先需要判断这题的类型:个人认为是现实的模拟题。假如你是老板,这里有个商品的价格为620美元,这时有个妹纸走进店里,说这个620美元的大大大宝石我要了,但是我这里只有六种面值的硬币,分别是1, 5, 10, 50, 100, 500,对应的数量是3 2 1 3 0 2,随便说一下啊我这人比较懒,如果你愿意收620个一块的硬币,那我也是可以给你的,可如果你想从我这里拿走最少的硬币,但是又刚好是620元,那你就得算算了。你好歹也是一个老板啊,就没见过这么矫情的妹子,不过生意嘛,利益第一,于是你就马上打开eclipse,准备敲……
~
怎么敲呢?已知条件肯定是要用上的:
1,六种面值的硬币,且已知对应的数量是多少;2,已知需要支付的金额。
要求:收取最少的硬币!!!
步骤:
1,使用对应的类型接收对应的数据;
2,我已经知道了硬币的数量,那么就是用for循环逐一判断每种硬币
3,要求最少的硬币?当然是越大面额的硬币老子越喜欢了。所以硬币的判断要从从大到小
4,判断需要支付的价格减去每种硬币的数量乘以对应的面值,保证不能为负数,我总不能倒给你钱吧
5,如果需要支付的价格已经等于零了,不好意思妹子,这题我只用了1秒,掏钱吧
递归法:
import java.util.Scanner;
public class CoinsQuestion递归 {
static int value[] = {1, 5, 10, 50, 100, 500};//每个硬币的面值
static int nums[], P, ans;//分别存储每种硬币的数量、需要支付的价格、存储硬币的花费数
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//接收题目给出的数字
nums = new int[6];//每个硬币面值的数量
for(int i = 0; i < 6; i++){
nums[i] = sc.nextInt();
}
P = sc.nextInt();//需要支付的价格
//最后打印存储花费的硬币数
System.out.println(f(5));
}
static int f(int n){
if(P==0){//出口呀
return ans;
}
if(n < 0)return 0;
int num1 = P/value[n];//存储最大的面值硬币的数量应该有多少
int min = Math.min(num1, nums[n]);//判断理论需要的硬币数和实际有的硬币数
ans += min;//存储本次花费的硬币数量
P -= value[n]*min;
return f(n-1);//递归呀
}
}
思路:
不知道对没对,我只有一个案例,而且我对于举反例这块还是比较新手的
步骤:
1,这题既然使用递归,那么代码量一般都会比较少的,这种方法比较抽象嘛,而且main方法里一般都是只有接收数据加输出递归方法的返回值的
2,和迭代法差不多,由大到小判断硬币的面值,用理论上需要花费的硬币的数目和实际上硬币的数目之间的最小值,被减去需要花费的价格
3,判断出口:1)如果需要花费的价格等于0,return,如果硬币的数量已经遍历完了……这不就是钱不够或者没零钱嘛,那就说明:妹纸,此物与你有缘无份啊
有时候真的佩服那些老师,这么简单的问题我都需要做这么久,而且写思路的时候会有一种厌烦的感觉,算心情浮躁吧