手机版 欢迎访问it开发者社区(www.mfbz.cn)网站

当前位置: > 开发

哑铃片重量组合问题

时间:2021/5/28 16:53:40|来源:|点击: 次

哑铃片重量组合问题

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&&currentWidth+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
 */

 

Copyright © 2002-2019 某某自媒体运营 版权所有