题目描述:
给定n种物品和一个背包。物品 i 的重量是wi,其价值为vi,背包的容量为c. 应该如何选择装入背包中的物品,使其装入背包中的物品的总价值最大? 提示:可以选择物品 i 的一部分装入,而不一定要全部装入背包。
输入
背包的容量 物品的个数
物品的价值 物品的重量
输出
装入的物品 【1代表装入,0代表不装入,非0非1代表部分装入】
样例输入
50 3
60 10
100 20
120 30
样例输出
1 1 0.666667
提示 输入重量和价值时,已经将物品按单位价值排序。
思路总结:
其实就是贪心算法的运用,每次我们都装入单位价值最大的,直到背包装满
但是有两种情况:
- 恰好装满,这种比较男的
- 最后一个物品,只装入部分
遇见的问题:
Java代码,提示一直是答案错误,折腾了很久,觉得思路没有错
最后发现是格式的问题,所以换的c++,由于老师用的是c++
问题解决所学到知识:
1.控制格式的输出:如果小数点后面有多的零,自动删除, 例如(1.220000 ----> 1.22, 1.0000 ----> 1.0, 0.000 ------>0 )
BigDecimal bigDecimal = new BigDecimal(String.valueOf(x));
System.out.print(bigDecimal.stripTrailingZeros().toPlainString()+" ");
2.二维数组的排序:使用java的Arrays.sort()
, 中的Comparator<float[]>()
// 进行二维数组的排序
返回值大于0,则需要交换位置, 返回值小于0,表示顺序正确 ,返回值等于0 ,表示相等
/**
* 返回值大于0,则需要交换位置, 返回值小于0,表示顺序正确 ,返回值等于0 ,表示相等
* */
float[][] a = new float[n][2];
Arrays.sort(a, new Comparator<float[]>() {
@Override
public int compare(float[] o1, float[] o2) {
if (o2[2] > o1[2]){
return 1;
}else{
return -1;
}
}
});
参考代码:
java:默认输入的没有按照单价排序
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
/**
* @author chenzi
*/
public class Main {
public static void main(String[] args) {
int maxWeight, n, i, j;
Scanner scanner = new Scanner(System.in);
maxWeight = scanner.nextInt();
n = scanner.nextInt();
float[][] a = new float[n][4];
for (i = 0; i < n; i++) {
for (j = 0; j < 2; j++) {
a[i][j] = scanner.nextFloat();
}
/*a[][2]用于存单价:价值/重量*/
a[i][2] = a[i][0] / a[i][1];
a[i][3] = i;
}
float[] result = new Main().Max_backpack(a, n, maxWeight);
for (float x : result
) {
BigDecimal bigDecimal = new BigDecimal(String.valueOf(x));
System.out.print(bigDecimal.stripTrailingZeros().toPlainString()+" ");
}
}
private float[] Max_backpack(float[][] a, int n, int maxWeight) {
float[] result = new float[n];
int current_maxWeight = 0;
// 进行二维数组的排序
/**
* 返回值大于0,则需要交换位置, 返回值小于0,表示顺序正确 ,返回值等于0 ,表示相等
*/
Arrays.sort(a, new Comparator<float[]>() {
@Override
public int compare(float[] o1, float[] o2) {
if (o2[2] > o1[2]){
return 1;
}else{
return -1;
}
}
});
for (int i = 0; i < n; i++) {
if (current_maxWeight < maxWeight && current_maxWeight + a[i][1] <= maxWeight) {
current_maxWeight += a[i][1];
result[(int)a[i][3]] = 1;
} else if (current_maxWeight < maxWeight && current_maxWeight + a[i][1] > maxWeight) {
result[(int)a[i][3]] = (float) (maxWeight - current_maxWeight) / a[i][1];
current_maxWeight = maxWeight;
}else {
break;
}
}
return result;
}
}
c++:输入已经按照单价排序
#include <iostream>
using namespace std;
/*------------------------------------------------------------------------------------------
c++ 传入二维数组必须是指定第二维或者使用指针
由于很久没有使用c++了,很多忘了,所以索性就在函数内输出了
不成文规定:不能再函数中做输入输出的,应该返回结果的
---------------------------------------------------------------------------------------*/
void maxLoading(float a[][2], int n, float maxWeight)
{
// c++不能返回数组,只能返回指针
float current_maxWeight = 0;
float result[n];
for (int i = 0; i < n; i++)
{
if (current_maxWeight < maxWeight && current_maxWeight + a[i][1] <= maxWeight)
{
current_maxWeight += a[i][1];
result[i] = 1;
}
else if (current_maxWeight < maxWeight && current_maxWeight + a[i][1] > maxWeight)
{
result[i] = (maxWeight - current_maxWeight) / a[i][1];
current_maxWeight = maxWeight;
}
else
{
// 简单分析得不满足前面两个判断,此时背包一定达到 maxWeight
break;
}
}
// 理应不该在这里做输出的
for (float x : result)
{
cout << x << " ";
}
}
int main()
{
int n;
float maxWeight;
cin >> maxWeight >> n;
float a[n][2];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 2; j++)
{
cin >> a[i][j];
}
}
maxLoading(a, n, maxWeight);
}