Помогите найти решение задачи на java [закрыт]

110
06 октября 2019, 22:00

Имеется следующая задача:

В спортивном зале города N появилась штанга и набор блинов с различными массами. Для занятия спортом необходимо распределить блины по двум концам штанги таким образом, чтобы суммарный вес по оба конца штанги был одинаковый. Рассчитайте максимальный вес, который смогут поднимать спортсмены при заданном наборе блинов (с допущением, что гриф штанги невесомый).

Решение должно быть представлено в виде java-программы, у которой:

На входе: массив целых чисел, обозначающих веса блинов, входящих в набор. На выходе: целое число, обозначающее максимальный вес, который можно поднять с заданным набором блинов.

Примеры:

    • На входе: [1,2,3,6]
    • На выходе: 12
    • Пояснение: можно нацепить блины {1,2,3} с одной стороны и блин {6} с другой, что в сумме даст 12.
    • На входе: [1,2,3,4,5,6]
    • На выходе: 20
    • Пояснение: можно нацепить блины {2,3,5} с одной стороны и блины {4,6} с другой, что в сумме даст 20. Оставшийся блин {1} не может быть нацеплен ни с одной из сторон без потери равновесия.
    • На входе: [1,2]
    • На выходе: 0
    • Пояснение: данный набор блинов невозможно нацепить без потери равновесия.

Ограничения:

  1. Блин может весить от 0 до 20 фунтов.
  2. В наборе может присутствовать от 1 до 1000 блинов.
  3. Суммарный вес целого набора не может превышать 10000 фунтов.

Сейчас учусь java и решаю задачи. Никак не могу найти подход к данной задачи. Помогите пожалуйста решить, или направьте мысль в нужное русло.

Answer 1

Например так

    List<Integer> weights = Arrays.asList(1, 2, 3, 6);
    int size = weights.stream()
            .mapToInt(x -> x)
            .sum() / 2 + 1;
    int[] arr = new int[size];
    arr[0] = 2;
    for (int weight : weights) {
        for (int i = size - 1; i >= 0; i--) {
            if (arr[i] > 0 && i + weight < size) {
                arr[i + weight]++;
            }
        }
    }
    for (int i = size - 1; i > 0; i--) {
        if (arr[i] >= 2) {
            System.out.println(i);
            break;
        }
    }

EDIT

Я все таки домучал. Решение получилось почти в лоб. Оно строит все возможные способы получить все возможные суммы. Затем находит наибольшую сумму у которой есть два не пересекающихся разложения.

public class App {
    public static void main(String[] args) {
        List<W> weights = Stream.of(1, 2, 3, 4, 5, 9)
                .map(W::new)
                .collect(Collectors.toList());
        Map<Integer, List<List<W>>> arr = new HashMap<>();
        arr.put(0, Collections.singletonList(Collections.emptyList()));
        for (W weight : weights) {
            arr = arr.entrySet().stream()
                    .flatMap(x -> {
                                int newWeight = x.getKey() + weight.value;
                                List<List<W>> newList = x.getValue().stream()
                                        .map(ArrayList::new)
                                        .peek(y -> y.add(weight))
                                        .collect(Collectors.toList());
                                return Stream.of(
                                        new Pair<>(newWeight, newList),
                                        new Pair<>(x.getKey(), x.getValue())
                                );
                            }
                    )
                    .collect(Collectors.toMap(
                            Pair::getIndex,
                            Pair::getValue,
                            (x, y) -> {
                                List<List<W>> r = new ArrayList<>(x);
                                r.addAll(y);
                                return r;
                            }));
        }
        arr.entrySet().
                stream()
                .sorted(Comparator.comparing(Map.Entry::getKey, Comparator.reverseOrder()))
                .filter(x ->
                {
                    for (List<W> a : x.getValue()) {
                        for (List<W> b : x.getValue()) {
                            if(a == b) continue;
                            if (a.stream().noneMatch(b::contains)) {
                                return true;
                            }
                        }
                    }
                    return false;
                })
                .map(Map.Entry::getKey)
                .findFirst()
                .ifPresent(System.out::println);
    }
    @Data
    static class Pair<T> {
        private final int index;
        public final T value;
    }
    @AllArgsConstructor
    @Getter
    static class W {
        public final int value;
    }
}

Класс W нужен чтобы различать блины с одинаковыми весами.

READ ALSO
Как в Spring зарегистрировать объект-бин, созданный через new?

Как в Spring зарегистрировать объект-бин, созданный через new?

Можно ли привязать простой объект к контексту во время выполнения?

100
Хранить картинку в памяти телефона

Хранить картинку в памяти телефона

Есть огромный массив с данными и картинками, после каждого раза входа в приложению заново загружает все картинки с интернета, что сделать...

109
Уведомления в определенном радиусе

Уведомления в определенном радиусе

Задача стоит в том что когда один пользователь нажмет на кнопку в андроид приложении например "Отослать уведомление"То его должны получать...

115
Как убрать серый фон в input и textarea в Internet Exporer

Как убрать серый фон в input и textarea в Internet Exporer

У меня для input и textarea есть собственные стили, убраны все лишние кнопки (стрелки, крестики, границы), и поставлен фон на чисто белыйВо всех браузерах...

111