Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.05.2019, 00:48   #1
WarM19
Новичок
Джуниор
 
Регистрация: 16.05.2019
Сообщений: 1
По умолчанию Задача на переливания (задача на граф)

В наличии имеется три сосуда, объемом N, M, K литров соответственно. Изначально они заполнены водой на X, Y, Z литров. Необходимо объем воды X + Y + Z разделить между сосудами так, чтобы в первом сосуде было P литров, во втором Q литров и в третьем R литров за минимально возможное число переливаний. Дополнительную воду использовать нельзя. Иногда такое разбиение выполнить невозможно.
Входные данные.
Данные читаются из файла с именем “input.txt”.
Структура файла:
N M K
X Y Z
P Q R
Выходные данные.
В файл “output.txt” вывести единственное число – число переливаний, необходимое для того, чтобы разделить воду между сосудами. Если разбиение осуществить невозможно, то вывести -1.
Ограничения.
1 <= N, M, K, X, Y, Z, P, Q, R <= 10000.
N >= X
M >=Y
K >= Z
X + Y + Z = P + Q + R
Не более 2 секунд на тест.
Пример.
Input.txt Output.txt
3 2 1 2
1 2 1
3 1 0
Очень надеюсь на помощь, если честно уже задолбался, надеюсь кто-нибудь поможет, заранее спасибо!
WarM19 вне форума Ответить с цитированием
Старый 17.05.2019, 11:42   #2
digitalis
Старожил
 
Аватар для digitalis
 
Регистрация: 04.02.2011
Сообщений: 4,546
По умолчанию

Все кинулись помогать и уткнулись в : на каком языке, соб-сно?
digitalis вне форума Ответить с цитированием
Старый 17.05.2019, 12:00   #3
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

3 переливания. (кто меньше? )

1, 2. X-P разлить во второй (X1) и третий (X-P-X1)
3. Y+X1-Q вылить в третий.
Цитата:
Иногда такое разбиение выполнить невозможно.
Z+(X-P-X1) +(Y+X1-Q) <> R

P.S. в требованиях задач кое-что пропущено.
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 17.05.2019, 12:01   #4
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Сообщение от digitalis Посмотреть сообщение
Все кинулись помогать и уткнулись в : на каком языке, соб-сно?
а Вы сможете алгоритм решения расписать?
можно просто словесный. Или в виде блок-схемы?

я, например, не могу.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 17.05.2019, 12:08   #5
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
3 переливания. (кто меньше? )
это Вы для какой задачи 3 переливания насчитали?

для контрпримера из пост #1 два:
1) сначала полностью выливаем 3-й сосуд в первый.
2) выливаем из второго в первый до полноты.
итог
3 1 0
Serge_Bliznykov вне форума Ответить с цитированием
Старый 17.05.2019, 13:00   #6
val_nnm
Форумчанин
 
Регистрация: 18.10.2009
Сообщений: 185
По умолчанию

Написал на C#
Код:
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Tuple<int, int, int> volume = new Tuple<int, int, int>(3, 2, 1);
            Tuple<int, int, int> target = new Tuple<int, int, int>(3, 1, 0);

            //Вновь полученные варианты которые нужно разливать другими способами
            HashSet<Tuple<int, int, int>> newAll = new HashSet<Tuple<int, int, int>>();
            newAll.Add(new Tuple<int, int, int>(1, 2, 1));

            //Все варианты уже рассмотренные ранее которые можно не обрабатывать заново
            HashSet<Tuple<int, int, int>> all = new HashSet<Tuple<int, int, int>>(newAll);

            int count = -1;
            while (newAll.Count>0)
            {
                count++;
                if (newAll.Contains(target)) break;
                HashSet<Tuple<int, int, int>> newAvailable = new HashSet<Tuple<int, int, int>>();
                foreach (var tmp in newAll)
                {
                    //Судя по условия X + Y + Z = P + Q + R воду выливать нельзя. Если воду выливать разрешено, то разкоментировать следующие строки.
                    //newAvailable.Add(new Tuple<int, int, int>(0, tmp.Item2, tmp.Item3)); // Выливаем воду из 1
                    //newAvailable.Add(new Tuple<int, int, int>(tmp.Item1, 0, tmp.Item3)); // Выливаем воду из 2
                    //newAvailable.Add(new Tuple<int, int, int>(tmp.Item1, tmp.Item2, 0)); // Выливаем воду из 3

                    {
                        var v = Math.Min(tmp.Item1, volume.Item2 - tmp.Item2);
                        newAvailable.Add(new Tuple<int, int, int>(tmp.Item1 - v, tmp.Item2 + v, tmp.Item3)); // Переливаем воду из 1 в 2
                    }

                    {
                        var v = Math.Min(tmp.Item1, volume.Item3 - tmp.Item3);
                        newAvailable.Add(new Tuple<int, int, int>(tmp.Item1 - v, tmp.Item2, tmp.Item3 + v)); // Переливаем воду из 1 в 3
                    }
                    {
                        var v = Math.Min(tmp.Item2, volume.Item1 - tmp.Item1);
                        newAvailable.Add(new Tuple<int, int, int>(tmp.Item1 + v, tmp.Item2 - v, tmp.Item3)); // Переливаем воду из 2 в 1
                    }
                    {
                        var v = Math.Min(tmp.Item2, volume.Item3 - tmp.Item3);
                        newAvailable.Add(new Tuple<int, int, int>(tmp.Item1, tmp.Item2 - v, tmp.Item3 + v)); // Переливаем воду из 2 в 3
                    }
                    {
                        var v = Math.Min(tmp.Item3, volume.Item1 - tmp.Item1);
                        newAvailable.Add(new Tuple<int, int, int>(tmp.Item1 + v, tmp.Item2, tmp.Item3 - v)); // Переливаем воду из 3 в 1
                    }
                    {
                        var v = Math.Min(tmp.Item3, volume.Item2 - tmp.Item2);
                        newAvailable.Add(new Tuple<int, int, int>(tmp.Item1, tmp.Item2 + v, tmp.Item3 - v)); // Переливаем воду из 3 в 2
                    }
                }
                newAll.Clear();
                foreach (var tmp in newAvailable)
                {
                    if (all.Add(tmp))
                    {
                        newAll.Add(tmp);
                    }
                }
            }
            if (newAll.Count == 0) count = -1;
            Console.WriteLine(count);
            Console.ReadLine();
        }
    }
}
Только полноценно тестировать код сейчас нет времени, воспринимайте это лишь как общую идею алгоритма решения. (в коде могут быть ошибки)
На С# пишу лучше чем на русском.
"У меня правильнописание хромает. Оно хорошее, но почему-то хромает."
val_nnm вне форума Ответить с цитированием
Старый 17.05.2019, 21:26   #7
ViktorR
Старожил
 
Регистрация: 23.10.2010
Сообщений: 2,306
По умолчанию

Так понимаю, что сосуды переставлять нельзя.
Цитата:
...разделить между сосудами так, чтобы в первом сосуде было P литров, во втором Q литров и в третьем R литров...
Если построить разности между тем, что есть и тем что необходимо, то станет понятно откуда брать и куда лить.
Код:
Input.txt	Output.txt
 3 2 1	           2
 1 2 1
 3 1 0
------
-2 1 1
Может есть и другие варианты?
Предварительно контролируем соответствие объёма сосуда требуемому объёму воды.
Как-то так, ...
ViktorR вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Переливания Алекс8 Паскаль, Turbo Pascal, PascalABC.NET 2 28.10.2013 20:52
Задача по подсчёту статистики использования букв. Другая задача - по длинной арифметике Pascal ABC kimberly Паскаль, Turbo Pascal, PascalABC.NET 3 24.12.2012 17:03
Задача на оптимальный расчет маршрута (задача в презентации) в табличном процессоре Excel Toofed Помощь студентам 0 30.11.2011 01:12
Задача на граф kopzone Помощь студентам 5 27.07.2008 23:14