Я пытаюсь решить следующее SPOJ проблема.
Ввод:
1. Общий вес определенной суммы денег в монетах,
2. значения и соответствующие веса монет используемой валюты.
Цель состоит в том, чтобы найти минимально возможную денежную оценку данной суммы денег.
Мой подход состоит в том, чтобы отсортировать монеты валюты по их соотношениям стоимости / веса в порядке возрастания, а затем, с жадностью, подгонять вес первой монеты столько раз, сколько возможно в общей сумме (отслеживая, сколько раз она подходит ), затем поместите вес второй монеты в остаток как можно больше раз и т. д. для всех монет или до тех пор, пока остаток не станет равным нулю (если это не так, ситуация невозможна).
Судья говорит, что мой ответ неверен. Можете ли вы дать мне подсказку о том, что неправильно в алгоритме?
Мой код здесь:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef unsigned int weight_t;
typedef unsigned int value_t;
struct coin {
weight_t weight;
value_t value;
double value_per_gram;
};
coin make_coin(weight_t weight, value_t value) {
coin ret;
ret.weight = weight;
ret.value = value;
ret.value_per_gram = (double)(value/weight);
return ret;
}
bool compare_by_value_per_gram(const coin& coin1, const coin& coin2) {
return coin1.value_per_gram < coin2.value_per_gram;
}
int main() {
unsigned int test_cases;
cin >> test_cases;
while(test_cases--) {
unsigned int number_of_coins = 0;
weight_t empty_pig, full_pig, coins_weight, coin_weight, min_value = 0;
value_t coin_value = 0;
vector<coin> coins;
vector<unsigned int> how_many_coins;
cin >> empty_pig >> full_pig;
coins_weight = full_pig - empty_pig;
cin >> number_of_coins;
while(number_of_coins--) {
cin >> coin_value >> coin_weight;
coins.push_back(make_coin(coin_weight, coin_value));
}
sort(coins.begin(), coins.end(), compare_by_value_per_gram);
how_many_coins.resize(coins.size());
for(unsigned int i = 0; i < coins.size() && coins_weight > 0; i++) {
how_many_coins[i] = coins_weight/coins[i].weight;
coins_weight %= coins[i].weight;
min_value += coins[i].value * how_many_coins[i];
}
if(coins_weight == 0) cout << "The minimum amount of money in the piggy-bank is " << min_value << "." << endl;
else cout << "This is impossible." << endl;
}
return 0;
}
Просто контрпример будет два типа монет (weight,value) = {(2,3), (3,3)}
с поросенком, который весит 4. Вы попытаетесь положить «худшую» монету весом 3 и не сможете соответствовать весу четырех. Но ситуация очень возможна с 2 * (2,3) монетами,
Это может быть решено очень похоже на проблема с рюкзаком, используя некоторую модификацию на Динамическое программирование решение:
Идея состоит в том, чтобы подражать исчерпывающему поиску. На каждом шаге вы смотрите на текущую монету-кандидата и у вас есть два варианта: взять ее или перейти к следующей монете.
f(x,i) = INFINITY x < 0 //too much weight
f(0,i) = 0 //valid stop clause, filled the piggy completely.
f(x,0) = INFINITY x > 0 //did not fill the piggy
f(x,i) = min{ f(x,i-1) , f(x-weight[i], i) + value[i] } //take minimal guaranteed value
^ ^
coin is not used use this coin
anymore
Вызвать с f(Weight,#coins_in_currency)
Временная сложность этого решения при использовании DP (снизу вверх или сверху вниз) составляет O(n*W)
где W
желаемый вес поросенка и n
количество монет в валюте