Матч 355, Смешивание жидкостей (MixingLiquids)

Дивизион 2, Уровень 3; Дивизион 1, Уровень 2

 

Если смешать x литров воды со (100 – x)  литрами субстанции, получим x% раствор субстанции. Имеется набор бутылок, содержащих растворы одной и той же субстанции. i - ая бутылка содержит amount[i] литров percent[i]% раствора субстанции. Необходимо определить наибольшее количество литров need% раствора, которое можно получить, смешивая содержимое бутылок (возможно, частичное).

 

Класс: MixingLiquids

Метод: double howMuch(vector<int> percent, vector<int> amount,

                      int need)

Ограничения: 0 £ percent[i] £ 100, 0 £ amount[i] £ 1000, 0 £ need £ 100.

 

Вход. Массив percent содержит процентный раствор субстанций в имеющихся бутылках, а amount содержит емкость  бутылок. Значение need содержит процентное содержание субстанции, которое следует получить.

 

Выход. Наибольшее количество литров need% раствора, которое можно получить, смешивая содержимое бутылок.

 

Пример входа

percent

amount

need

{0, 100}

{20, 30}

50

{90, 70, 80}

{10, 10, 10}

50

{30, 80, 60}

{40, 10, 15}

57

 

Пример выхода

40.0

0.0

35.18518518518519

 

 

РЕШЕНИЕ

жадный алгоритм

 

Вычислим процентное содержание субстанции в растворе, полученном сливанием жидкостей со всех бутылок. Для этого следует найти общее количество субстанции и общий объем жидкости. Если полученное процентное содержание меньше (больше) требуемого значения need, то следует изъять из раствора бутылку с наименьшим (наибольшим) процентом содержания субстанции. Очевидно, что в таком случае процентное содержание субстанции в общем растворе увеличится (уменьшится). Продолжаем процесс последовательного изъятия из общего раствора бутылок, пока процентное содержание субстанции не пересечет значение need. Предположим, что указанное пересечение значения need произошло как раз на i-ой бутылке. Значит, нам необходимо взять из i-ой бутылки какую-то часть раствора, чтобы получить в точности need% раствор.

 

ПРОГРАММА

 

#include <cstdio>

#include <vector>

#include <numeric>

#include <set>

#include <algorithm>

using namespace std;

 

class MixingLiquids

{

public:

  double howMuch(vector<int> percent, vector<int> amount, int need)

  {

    int i,j,totSubstance,

        totAmount = accumulate(amount.begin(),amount.end(),0);

    vector<pair<int,int> > v;

 

    for(totSubstance=i=0;i<percent.size();i++)

      totSubstance += percent[i]*amount[i];

 

    for(i=0;i<percent.size();i++)

      v.push_back(make_pair(percent[i],amount[i]));

    sort(v.begin(),v.end());

 

    i = 0; j = v.size()-1;

    while(i<=j)

    {

      if (totSubstance == need*totAmount) return totAmount;

      if (totSubstance < need*totAmount)

      {

        int _totSubstance = totSubstance - v[i].first*v[i].second;

        int _totAmount = totAmount - v[i].second;

        if (_totSubstance > need*_totAmount)

          return _totAmount+

                 1.0*(need*_totAmount - _totSubstance)/(v[i].first - need);

        else

        {

          totSubstance = _totSubstance;

          totAmount = _totAmount;

          i++;

        }

      }

 

      if (totSubstance > need*totAmount)

      {

        int _totSubstance = totSubstance - v[j].first*v[j].second;

        int _totAmount = totAmount - v[j].second;

        if (_totSubstance < need*_totAmount)

           return _totAmount+

                  1.0*(need*_totAmount - _totSubstance)/(v[j].first - need);

        else

        {

          totSubstance = _totSubstance;

          totAmount = _totAmount;

          j--;

        }

      }

    }

 

    return 0;

  }

};