Java 贪心思想

说到“贪”字,很邪恶的一个词,记得和珅和大人拆解过这个字,为”今“和”贝“,而”贝“字分解成”上面的那个XX“和”人“,意思就是说
今天你贪了,明天一座监狱就把你套起来,纵观古今,有多少豪杰与"贪“结下了不解之缘,呵呵,扯远了。

这个贪心的行为在算法中也成为了一种指导思想,也就是说贪心算法所作出的选择在当时的环境下是最好的,说深一点就是它只是某种
意义上的局部最优解,但不一定是全局最优解,此时往往接近于最优解。

一: 优点
前面也说了,贪心只是求的当前环境下的最优解,而不是追究整体的最优解,所以贪心就避免了为求的整体最优解而枚举各种方案所
耗费的时间。

二: 问题
① 不能保证贪心所得出的解是整体最优的。
② 不能用来求最大解和最小解问题。
③ 只能求满足某些约束条件的可行解的范围。

三: 案例
其实说到贪心,基本上都会提到“背包问题”,这里我就举一个“找零钱的问题“,对的,找零钱问题是我们生活中一个活生生的贪心算法
的例子,比如我买了“康师傅来一桶方便面”,给了10两银子,方便面3.8两,那么收银mm该找我6.2两,现实中mm不自觉的就会用到贪心的行
为给我找最少张币,总不能我给mm一张,mm给我十几张,那样mm会心疼的。
此时mm提供的方案就是:5元1张,1元1张,2角1张。

闲话不说,上代码:

package com.jiaozg.algorithm.feibonaqie;

import java.util.Scanner;

import org.junit.Test;

public class Tanxin {

public void getChange(float money) {

int yuan100 = 0, yuan50 = 0, yuan20 = 0, yuan10 = 0, yuan5 = 0, yuan1 = 0, coin5 = 0, coin2 = 0, coin1 = 0;

/**
* 下面采用循环递减方式写demo
*/
while (money >= 100d) {
yuan100++;
money -= 100d;
}
while (money >= 50d) {
yuan50++;
money -= 50d;
}
while (money >= 20d) {
yuan20++;
money -= 20d;
}
while (money >= 10d) {
yuan10++;
money -= 10d;
}
while (money >= 5d) {
yuan5++;
money -= 5d;
}
while (money >= 1d) {
yuan1++;
money -= 1d;
}
while (money >= 0.5d) {
coin5++;
money -= 0.5d;
}
while (money >= 0.2d) {
coin2++;
money -= 0.2d;
}
while (money >= 0.1d) {
coin1++;
money -= 0.1d;
}
System.out.println("需找零:");
if (yuan100 > 0) {
System.out.println("100元 " + yuan100 + "张");
}
if (yuan50 > 0) {
System.out.println("50元 " + yuan50 + "张");
}
if (yuan20 > 0) {
System.out.println("20元 " + yuan20 + "张");
}
if (yuan10 > 0) {
System.out.println("10元 " + yuan10 + "张");
}
if (yuan5 > 0) {
System.out.println("5元 " + yuan5 + "张");
}
if (yuan1 > 0) {
System.out.println("1元 " + yuan1 + "张");
}
if (coin5 > 0) {
System.out.println("5角 " + coin5 + "张");
}
if (coin2 > 0) {
System.out.println("2角 " + coin2 + "张");
}
if (coin1 > 0) {
System.out.println("1角 " + coin1 + "张");
}
}

@Test
public void testTanxinSuanFa() {
while (true) {
System.out.println("请付款(精确到1角):");
Scanner scanner = new Scanner(System.in);
float money = scanner.nextFloat();
getChange(money);
}
}
}


输出结果:
请付款(精确到1角):
1688.8
需找零:
100元 16张
50元 1张
20元 1张
10元 1张
5元 1张
1元 3张
5角 1张
2角 1张
1角 1张

但是我发现了一个问题,如果输入78.6的话,输出是不对的
78.6
需找零:
50元 1张
20元 1张
5元 1张
1元 3张
5角 1张
请付款(精确到1角):

少了一角,debug发现和一角比较的时候,那个数编程0.099999999999,所以一角就没有输出
这个问题的详细说一下
[b]小数精确计算[/b]

System.out.println(2.00 -1.10);//0.8999999999999999
上面的计算出的结果不是 0.9,而是一连串的小数。问题在于1.1这个数字不能被精确表示为一个double,因此它被表示为最接近它的double值,该程序从2中减去的就是这个值,但这个计算的结果并不是最接近0.9的double值。
一般地说,问题在于并不是所有的小数都可以用二进制浮点数精确表示。
二进制浮点对于货币计算是非常不适合的,因为它不可能将1.0表示成10的其他任何负次幂。

解决问题的第一种方式是使用货币的最小单位(分)来表示:System.out.println(200-110);//90

第二种方式是使用BigDecimal,但一定要用BigDecimal(String)构造器,而千万不要用BigDecimal(double)来构造(也不能将float或double型转换成String再来使用BigDecimal(String)来构造,因为在将float或double转换成String时精度已丢失)。例如new BigDecimal(0.1),它将返回一个BigDecimal,也即0.1000000000000000055511151231257827021181583404541015625,正确使用BigDecimal,程序就可以打印出我们所期望的结果0.9:
System.out.println(new BigDecimal("2.0").subtract(new BigDecimal("1.10")));// 0.9

另外,如果要比较两个浮点数的大小,要使用BigDecimal的compareTo方法。

参考:http://blog.csdn.net/m13666368773/article/details/7531473
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值