Determining the maximum value that can be obtained from a loot
The algorithm
Your algorithm needs O(n) space (for storing all items), and O(n * k) time (for selecting the best ones) (n = items to choose from, k = items chosen, bounded by n).
By choosing as you go, you can get that down to O(k') space and O(n * k') time (k' = maximum items chosen at any time, at least k, bounded by n).
Take a look at std::push_heap, std::tuple and lambdas for implementing the new algorithm.
Avoid casting
Casting is error-prone, as it circumvents the protections of the type-system. Thus, use the most restricted cast you can, and don't cast at all if reasonably possible. In your case, why not multiply with 1.0 instead?
Floating-point is hard
You are calculating the specific value (value per weight) of your items for comparison purposes. Luckily, a double has enough precision that you are extremely unlikely to suffer from rounding-errors when dividing two 32 bit numbers. Still, instead of comparing 1.0 * a_value / a_weight &lt; 1.0 * b_value / b_weight you could compare 1LL * a_value * b_weight &lt; 1LL * b_value * a_weight, avoiding division and floating-point.
All those useless copies
While copying small trivial types is generally the right approach, a std::vector is neither small nor trivial; Copying it is rather expensive. If you only need to read it, use a constant reference or preferably a C++2a std::span for increased flexibility.
Gracefully handle all kinds of invalid input
No need to assume malice, you are assured your load of garbage anyway.
Just the code

I don't see where you use anything from &lt;cstdio&gt;, so don't include it.

Never import a namespace wholesale which isn't designed for it. Especially std is huge and ever-changing, which can silently change the meaning of your code even between minor revisions of your toolchain, let alone using a different one.
It cannot be guaranteed to break noisily.

return 0; is implicit for main(). Make of that what you will.