哑铃片重量组合问题
import java.io.BufferedInputStream;
import java.util.*;
class Pair<K,V> {
public final K key;
public final V value;
public Pair(K k, V v) {
key = k;
value = v;
}
} ///:~
class Combination implements Comparable{
public ArrayList<Double> plates = new ArrayList<>();
public double leftWidth; // 安装了哑铃片和卡扣后剩下的距离
public double getSum() {
double sum=0;
for (Double weight:plates) {
sum+=weight;
}
return sum;
}
public void print() {
StringBuilder sb = new StringBuilder();
double sum=getSum();
sb.append(sum+" \t= ");
for (int i=0; i<plates.size(); i++) {
if (i==plates.size()-1) {
sb.append(plates.get(i));
} else {
sb.append(plates.get(i)+" + ");
}
}
if (leftWidth<1.3) {
sb.append("(极限长度,注意安全)");
}
System.out.println(sb);
}
@Override
protected Combination clone() throws CloneNotSupportedException {
Combination combination = new Combination();
combination.plates.addAll(this.plates);
return combination;
}
@Override
public int hashCode() {
int hash=0;
for (Double weight:this.plates) {
hash += weight.hashCode();
}
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Combination) {
Combination combination = (Combination) obj;
if (this.plates.size()!=combination.plates.size()) {
return false;
}
for (int i=0; i<this.plates.size(); i++) {
if (!this.plates.get(i).equals(combination.plates.get(i))) {
return false;
}
}
return true;
} else {
return false;
}
}
@Override
public int compareTo(Object o) {
Combination combination = (Combination) o;
if (this.equals(combination)) {
return 0;
}
double delta = this.getSum()-combination.getSum();
if (delta>-0.0000001&&delta<0.0000001) {
if (this.plates.size()==combination.plates.size()) {
return 1;
}
return this.plates.size()-combination.plates.size();
} else if (delta<0) {
return -1;
} else {
return 1;
}
}
}
public class Solution {
private ArrayList<Pair<Double, Double>> num = new ArrayList<>(); // 可供选择的哑铃片,key=重量,value=厚度
private Set<Double> res = new HashSet<>(); // 不同的重量
private Set<Combination> combinationSet = new TreeSet<>(); // 不同的方案
private Double WIDTH=18.2; // 哑铃杆单侧长度
private Double FASTENER_WIDTH=1.7; // 卡扣厚度
public static void main(String[] args) {
new Solution().solve();
}
private void add(double weight, double width) {
num.add(new Pair<Double, Double>(weight, width));
}
private void dfs(int index, Combination currentCombination, double currentWeight, double currentWidth) throws CloneNotSupportedException {
if (index>=num.size()) {
if (currentWeight>0&¤tWidth+FASTENER_WIDTH<=WIDTH) {
Combination clone = currentCombination.clone();
clone.leftWidth=WIDTH-currentWidth-FASTENER_WIDTH;
combinationSet.add(clone);
res.add(currentWeight);
}
return;
}
// 不选当前哑铃片
dfs(index+1, currentCombination, currentWeight, currentWidth);
// 选当前哑铃片
currentCombination.plates.add(num.get(index).key);
dfs(index+1, currentCombination, currentWeight+num.get(index).key, currentWidth+num.get(index).value);
currentCombination.plates.remove(currentCombination.plates.size()-1);
}
public void prepare() {
// 对可供选择的哑铃片按照重量从小到大排序
// 这样每个Combination里存放的哑铃片也一定是按照重量从小到大排序的
for (int i=0; i<num.size(); i++) {
int minIndex = i;
for (int j=i+1; j<num.size(); j++) {
if (num.get(j).key<num.get(minIndex).key) {
minIndex=j;
}
}
if (minIndex!=i) {
Pair<Double, Double> temp = num.get(minIndex);
num.set(minIndex, num.get(i));
num.set(i, temp);
}
}
}
public void solve() {
Scanner cin = new Scanner(new BufferedInputStream(System.in));
System.out.println("请输入哑铃杆子单侧可放置哑铃片的宽度(cm):");
WIDTH=cin.nextDouble();
System.out.println("请输入卡扣的安全扣宽(cm):");
FASTENER_WIDTH=cin.nextDouble();
System.out.println("请输入哑铃片的个数:");
int n = cin.nextInt();
System.out.println("请输入"+n+"个哑铃片的重量(kg)和厚度(cm),每片的重量和厚度空格分隔,片与片分行:");
while ((n--)>0) {
double weight = cin.nextDouble();
double width = cin.nextDouble();
add(weight, width);
}
prepare();
Combination currentCombination = new Combination();
try {
dfs(0, currentCombination, 0, 0);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println("---------------------");
for (Combination combination:combinationSet) {
combination.print();
}
System.out.println("---------------------");
System.out.println("共计"+res.size()+"种组合重量");
System.out.println("共计"+combinationSet.size()+"种组合方案");
}
}
/*
18.2
1.7
3
4 4.15
5.5 4.15
5.5 4.15
*/
/*
18.2
1.7
4
2.5 3.1
5.0 3.8
6.0 4.25
6.0 4.25
*/
/*
18.2
1.7
7
4 4.15
5.5 4.15
5.5 4.15
2.5 3.1
5.0 3.8
6.0 4.25
6.0 4.25
*/