假设您有一个顶点图。每个顶点到那里旅行都需要花费1美元,但是访问它也会获得比特币奖励。每个顶点都有一个相对于其他每个顶点以及自身的边缘。到给定顶点的成本是相同的,无论它是来自自身还是来自任何其他顶点。到给定顶点的奖励是相同的,无论是来自其本身还是来自任何其他顶点。示例:
顶点A:访问费用为$ 20,奖励为25比特币。
B点:访问费用为15美元,奖励为19个比特币。
顶点C:访问成本为6美元,奖励为7个比特币。
我可以用N美元在任何顶点开始。我想用我的美元获得尽可能多的比特币。如果我有$ 41,则在上面的示例中,我可以按任意顺序访问A,B,C一次,从而获得51个比特币。如果我有$ 40,则可以通过两次访问A获得50个比特币。
我已尝试通过暴力破解此问题
#include <iostream>
#include <tuple>
#include <iterator>
#include <list>
#include <vector>
struct vertex_t
{
int dollar_cost = 0;
int bitcoin_reward = 0;
};
int try_visit_vertex(int& dollars, const vertex_t& vertex)
{
if (dollars >= vertex.dollar_cost)
{
dollars -= vertex.dollar_cost;
return vertex.bitcoin_reward;
}
return 0; // couldn't visit
}
auto enumerateVertices(const std::tuple<int, int>& status, const std::vector<vertex_t>& vertices)
{
std::list<std::tuple<int, int>> bitcoinsObtainedAndDollarsRemaining;
for (auto& vertex : vertices)
{
auto dollars_remaining = std::get<1>(status);
const auto bitcoinsObtained = try_visit_vertex(dollars_remaining, vertex);
if (bitcoinsObtained)
bitcoinsObtainedAndDollarsRemaining.push_back(std::make_tuple(std::get<0>(status) + bitcoinsObtained, dollars_remaining));
}
return bitcoinsObtainedAndDollarsRemaining;
}
int most_bitcoins(const int dollars, const std::vector<vertex_t>& vertices)
{
int maxBitcoinsObtained = 0;
std::list bitcoinsObtainedAndDollarsRemaining = { std::make_tuple(0, dollars) };
while (!bitcoinsObtainedAndDollarsRemaining.empty())
{
auto& front = bitcoinsObtainedAndDollarsRemaining.front();
maxBitcoinsObtained = std::max(maxBitcoinsObtained, std::get<0>(front));
auto backOfQueue = enumerateVertices(front, vertices);
bitcoinsObtainedAndDollarsRemaining.pop_front();
bitcoinsObtainedAndDollarsRemaining.splice(std::end(bitcoinsObtainedAndDollarsRemaining), backOfQueue);
}
return maxBitcoinsObtained;
}
int main()
{
std::cout << most_bitcoins(41, { { 20, 25 }, { 15, 19 }, { 6, 7 } });
}
我正在寻找更高效的人。我怀疑性能改进将是防止例如枚举时重复如果我push_back(A,A,B);我不应该后退(A,B,A)或(B,A,A)。甚至更好。。。不要压入任何重复的dollar_remaining + reward_amount元组。