Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.85/34: Рейтинг темы: голосов - 34, средняя оценка - 4.85
4 / 4 / 0
Регистрация: 03.12.2015
Сообщений: 22

Алгоритмы с возвратом. Задача о весах

02.10.2016, 17:08. Показов 6483. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, попытался разобраться с данной задачкой на с++, но ничего не получилось. Нашел в интернете ее на как я понял паскале, но т.к. я его знаю мягко сказать не очень ничего дельного не получилось. Вот сама задача, код на паскале и то что я попытался сделать на с++. Ошибка скорее всего в циклах for и скорее всего не верно возвращаю значение. Пожалуйста помогите.

УСЛОВИЕ. Имеется разновес, причем гиря определенного веса может быть представлена в нескольких экземплярах.
ВОПРОС. Набрать заданный вес всеми возможными способами с точностью до перестановки гирь.
ПРИМЕР. Разновес: 8, 7, 3, 2, 2, 1, 1, 1.
Набрать вес: 10кг.
Разновес удобно хранить в массиве KRATN[1..N], где N – вес самой тяжелой гири и KRATN[g] – количество экземпляров гири веса g.
Решение (набор веса) будем хранить в массиве SOL[1..N], где SOL[g] – количество экземпляров гири веса g в данном наборе.

Применим обычную схему алгоритма с возвратом.
Пусть V – текущий вес, который нужно набрать. Чтобы набрать этот вес, будем перебирать гири разновеса до тех пор, пока не встретим допустимую.
Условие допустимости:
Гиря g – допустима, если она имеется в разновесе, то есть KRATN[g]>0 и ее вес не превышает набираемого веса V, т.е. g≤V.
Пусть такая g найдена, удалим ее из разновеса, то есть KRATN[g]=KRATN[g]-1 и добавим к решению, то есть SOL[g]=SOL[g]+1. Новый текущий набираемый вес V1=V-g. Затем вызываем рекурсию для уменьшенного веса.
Возврат:
Если допустимой гири в разновесе нет или найдено решение, то последнюю добавленную гирю удаляем из решения и добавляем в разновес.
KRATN[g]=KRATN[g]+1; SOL[g]=SOL[g]-1; V=V1+g – текущий набираемый вес.
Затем возвращаемся на цикл перебора гирь разновеса и вместо гири g берем гирю g-1.

При такой схеме алгоритм будет генерировать повторяющиеся решения. Например, вес 10 будет набран как 2+8 и 8+2. Чтобы избавиться от повторов, будем генерировать решения в антиалфавитном порядке. Это означает следующее.
После того, как к решению была добавлена гиря веса g разрешено брать гири веса меньшего либо равного g. Таким образом, будет сгенерировано только решение 8+2.
Алгоритм {задача о весах}
Данные: разновес, представленный массивом KRATN[1…Ves], Ves – набираемый целый положительный вес.
Результат: печать наборов веса Ves без перестановок гирь.
Переменные: Ves, KRATN, SOL – глобальные.


Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1   procedure nabor (V, g);
{V - набираемый вес, g - вес последней добавленной к решению гири}
    begin {nabor}
    for i = g downto 1 do
    if (KRATN[i]>0) and (i≤V) then
    begin
    KRATN[i] = KRATN[i]-1;
    SOL[i] = SOL[i]+1;
    V1 = V-i;
    if V1=0 then печать SOL
    else nabor(V1, i);
{возврат}
    KRATN[i] = KRATN[i]+1;
    SOL[i] = SOL[i]-1;
    end;
 end; {nabor}
 
begin {main}
инициализация массива KRATN;
for j:=1 to Ves do SOL[J]:= 0;
nabor(Ves, Ves);
end.

То, что я попытался сделать.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "stdafx.h"
#include "iostream"
 
 
const int N = 8;
int ves = 10;
unsigned int KRATN[N] = { 1,1,1,2,2,3,7,8 }; // Разновес
unsigned int SOL[N]; //Набор веса
using namespace std;
unsigned int result;
 
unsigned int nabor(int V, int g)
{
    int V1; //V - набираемый вес, V1 - текущий набираемый вес, g - вес последней добавленной к решению гири
    for (int i = 1; i <= V; i++) // не знаю как переделать for i = g downto 1 do, по идее i-- вот так должно идти
    {
        if (KRATN[i] > 0 && i <= V)
        {
            KRATN[i] = KRATN[i] - 1;
            SOL[i] = SOL[i] + 1;
            V1 = V - i;
            if (V1 == 0)
            {
                cout << SOL[i] << " ";
            }
            else nabor(V1, i);
        }
        return  KRATN[i] = KRATN[i] + 1;
            SOL[i] = SOL[i] - 1;
    }
}
 
int main()
{
    setlocale(LC_ALL, "Russian");
    
 
    nabor(ves, ves);
 
 
    system("pause");
    return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
02.10.2016, 17:08
Ответы с готовыми решениями:

Алгоритмы разветвляющейся структуры: Определить можно ли взвесить покупку на весах
Весы могут выдержать груз до 10 кг.. Определите можно ли на них взвесить покупку из n кг картофеля, m кг огурцов и k кг томатов

Алгоритмы с возвратом
У Томми есть много бумажных квадратиков. Длинна из стороны (размер) изменяется от 1 до N – 1, и у него есть неограниченное число квадратов...

Алгоритмы с возвратом
Задача сложная, по этому и прошу помощи. Безопасные пути. В некотором царстве есть система дорог, представляющая собой...

2
 Аватар для regio1961
601 / 293 / 178
Регистрация: 06.06.2016
Сообщений: 552
02.10.2016, 23:35
По смыслу кода на Pascale разновес 8, 7, 3, 2, 2, 1, 1, 1 нужно представить массивом { 0, 3, 2, 1, 0, 0, 0, 1, 1 } ( 3 гири по 1кг,
2 гири по 2 кг, 1 -- по 3 кг и т.д, нумерация идет с нуля)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
 
 using namespace std;
 
 const int    N         = 9;
 const int    ves       = 10;
 unsigned int KRATN[N]  = { 0, 3, 2, 1, 0, 0, 0, 1, 1 }; // Разновес
 unsigned int SOL[N]; //Набор веса
 
 void  nabor( int V, int g )
 {
       for ( int i = g; i > 0; --i )
       {
             if ( ( KRATN[ i ] > 0 ) && ( i <= V ) )
             {
               --KRATN[i];
               ++SOL[i];
               int V1 = V - i;
                   if ( V1 == 0 )
                   {
                         for ( int j = 0; j < ves; j++ )
                         {
                             if ( SOL[j] )
                                for ( int k = SOL[j]; k > 0; k-- )
                                    cout << j << " ";
                         }
                     cout<<endl;
                   }
                   else
                     nabor( V1, i );
               // возврат:
               ++KRATN[i];
               --SOL[i];
             }
       }
 }
 //--------------------------------------------------------------------
 int main()
 {
   setlocale( LC_ALL, "Russian" );
 
   for ( int j = 0;  j < N; ++j )
     SOL[j] = 0;
 
   nabor( ves, ves );
 
   system("pause");
   return 0;
 }
Обозначения и глобальные переменные оставляю на вашей совести
0
2 / 2 / 0
Регистрация: 09.06.2021
Сообщений: 3
26.06.2021, 21:38
Просто оставлю это здесь может кому пригодится когда.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def getWeight(weight,last):
    # weight - требуемый вес, last - вес последней добавленной гири
    for i in reversed(range(1, last+1)):
        if kratn[i] > 0 and i <= weight:
            # Перебираем гири разновеса от большей к меньшей. Если количество гирь данного веса
            # больше 0,а ее вес меньше требуемого веса, убираем ее из разновеса и
            # добавляем к набираемому весу
            kratn[i] -= 1
            sol[i] += 1
            # Оставшийся вес равен требуемому весу минус вес добавленной гири
            weightRemaining = weight-i
            # Если оставшийся вес - 0, решение найдено, выводим решение на экран
            if weightRemaining == 0:
                for j in range(1,10):
                    print(sol[j], end='\t')
                print('\n')
            else: # иначе продолжаем подбор
                getWeight(weightRemaining,i)
            # Выполняем возврат, убираем гирю из набираемого веса
            # и возвращаем в разновес
            sol[i] -= 1
            kratn[i] += 1
 
# Создаем разновес
kratn = [0,3,0,1,1,0,0,1,1,1]
# Создаем список для набираемого веса
sol = [0,0,0,0,0,0,0,0,0,0]
# Выводим шапку таблицы
print('1кг\t2кг\t3кг\t4кг\t5кг\t6кг\t7кг\t8кг\t9кг\t')
getWeight(9,9)
input('Для продолжения нажмите клавишу Enter...')
Оно же без глобальных переменных:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
def getWeight(weight,last,kratn,sol):
    # weight - требуемый вес, last - вес последней добавленной гири
    for i in reversed(range(1, last+1)):
        if kratn[i] > 0 and i <= weight:
            # Перебираем гири разновеса от большей к меньшей. Если количество гирь данного веса
            # больше 0,а ее вес меньше требуемого веса, убираем ее из разновеса и
            # добавляем к набираемому весу
            kratn[i] =kratn[i] - 1
            sol[i] += 1
            # Оставшийся вес равен требуемому весу минус вес добавленной гири
            weightRemaining = weight-i
            # Если оставшийся вес - 0, решение найдено, выводим решение на экран
            if weightRemaining == 0:
                for j in range(1,10):
                    print(sol[j], end='\t')
                print('\n')
            else: # иначе продолжаем подбор
                getWeight(weightRemaining,i, kratn, sol)
            # Выполняем возврат, убираем гирю из набираемого веса
            # и возвращаем в разновес
            sol[i] -= 1
            kratn[i] += 1
 
def main():
    # Создаем разновес
    kratn = [0,0,0,0,0,0,0,0,0,0]
    try:
        for i in range(1,10):
            kratn[i] = int(input('Введите количество гирь весом '+ str(i) + 'кг: '))
        weight = int(input('Введите вес, который необходимо набрать, кг: '))
    except:
        print('Введены некорректные данные')
        return
    # Создаем пустой список для решения
    sol = [0,0,0,0,0,0,0,0,0,0]
    # Выводим шапку таблицы
    print('1кг\t2кг\t3кг\t4кг\t5кг\t6кг\t7кг\t8кг\t9кг\t')
    getWeight(weight, 9, kratn, sol)
    input('Для продолжения нажмите клавишу Enter...')
 
main()
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.06.2021, 21:38
Помогаю со студенческими работами здесь

Функция с возвратом указателя и возвратом ссылки
Найти максимальный и минимальный элемент в двумерном массиве и указать их номера. Указать номер первого отрицательного числа в массиве;...

Задача коммивояжёра с возвратом в "магазин"
Вроде и тема раскрытая (код можно найти, для этой задачи), но что-то я застрял на retract(oil(To,Y)), По условию задачи продавец...

Задача на эффективные алгоритмы
Я пытаюсь решить задачу на эффективные алгоритмы: На вход программы подаются заглавные латинские буквы, ввод этих символов заканчивается...

Задача на алгоритмы ветвления
К финалу конкурса лучшего по профессии &quot;Специалист электродорожник&quot; были допущены трое: Иванов, Петров, Сидоров. Соревнования проходили в 3...

Разветвляющиеся алгоритмы - Задача о смесях
Помогите написать программу в Delphi. Или хотя бы объясните примерный алгоритм, как делать... ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru