la risposta accettata, mentre un elegante pezzo di codice dal punto di vista del programmatore, non dà il miglior prezzo possibile per il cliente e, pertanto, potrebbe non essere una soluzione elegante dal punto di vista del cliente. Ad esempio, quando n = 4, la risposta accettata restituisce $ 1196, ma un cliente preferirebbe ovviamente scegliere il pacchetto di licenze 5 e pagare solo $ 999.
È possibile costruire un algoritmo che può calcolare il prezzo minimo possibile che il cliente può pagare per acquistare il numero di licenze richiesto. Un modo per farlo è usare la programmazione dinamica. Penso che qualcosa di simile potrebbe fare il trucco:
int calculatePrice(int n, Dictionary<int, int> prices)
{
int[] best = new int[n + prices.Keys.Max()];
for (int i = 1; i < best.Length; ++i)
{
best[i] = int.MaxValue;
foreach (int amount in prices.Keys.Where(x => x <= i))
{
best[i] = Math.Min(best[i],
best[i - amount] + prices[amount]);
}
}
return best.Skip(n).Min();
}
void Run()
{
Dictionary<int, int> prices = new Dictionary<int, int> {
{ 1, 299 },
{ 5, 999 },
{ 10, 1899 },
{ 20, 3499 },
{ 50, 7999 }
};
Console.WriteLine(calculatePrice(136, prices));
Console.WriteLine(calculatePrice(4, prices));
}
uscita:
22694
999
Aggiornamento Produrre un guasto è un po 'più complicato, ma io sicuramente penso che sarà utile per i tuoi clienti Si potrebbe fare qualcosa di simile (assumendo la stampa alla console, anche se un vero e proprio programma sarebbe probabilmente uscita a una pagina Web):
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static Dictionary<int, int> prices = new Dictionary<int, int> {
{ 1, 299 },
{ 5, 999 },
{ 10, 1899 },
{ 20, 3499 },
{ 50, 7999 }
};
class Bundle
{
public int Price;
public Dictionary<int, int> Licenses;
}
Bundle getBestBundle(int n, Dictionary<int, int> prices)
{
Bundle[] best = new Bundle[n + prices.Keys.Max()];
best[0] = new Bundle
{
Price = 0,
Licenses = new Dictionary<int, int>()
};
for (int i = 1; i < best.Length; ++i)
{
best[i] = null;
foreach (int amount in prices.Keys.Where(x => x <= i))
{
Bundle bundle = new Bundle
{
Price = best[i - amount].Price + prices[amount],
Licenses = new Dictionary<int,int>(best[i - amount].Licenses)
};
int count = 0;
bundle.Licenses.TryGetValue(amount, out count);
bundle.Licenses[amount] = count + 1;
if (best[i] == null || best[i].Price > bundle.Price)
{
best[i] = bundle;
}
}
}
return best.Skip(n).OrderBy(x => x.Price).First();
}
void printBreakdown(Bundle bundle)
{
foreach (var kvp in bundle.Licenses) {
Console.WriteLine("{0,2} * {1,2} {2,-5} @ ${3,4} = ${4,6}",
kvp.Value,
kvp.Key,
kvp.Key == 1 ? "user" : "users",
prices[kvp.Key],
kvp.Value * prices[kvp.Key]);
}
int totalUsers = bundle.Licenses.Sum(kvp => kvp.Key * kvp.Value);
Console.WriteLine("-------------------------------");
Console.WriteLine("{0,7} {1,-5} ${2,6}",
totalUsers,
totalUsers == 1 ? "user" : "users",
bundle.Price);
}
void Run()
{
Console.WriteLine("n = 136");
Console.WriteLine();
printBreakdown(getBestBundle(136, prices));
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("n = 4");
Console.WriteLine();
printBreakdown(getBestBundle(4, prices));
}
static void Main(string[] args)
{
new Program().Run();
}
}
uscita:
n = 136
2 * 50 users @ $7999 = $ 15998
1 * 20 users @ $3499 = $ 3499
1 * 10 users @ $1899 = $ 1899
1 * 5 users @ $ 999 = $ 999
1 * 1 user @ $ 299 = $ 299
-------------------------------
136 users $ 22694
n = 4
1 * 5 users @ $ 999 = $ 999
-------------------------------
5 users $ 999
Con cosa esattamente hai bisogno di aiuto?Stai cercando di capire come scelgono lo schema di prezzo appropriato per i valori superiori ai pacchetti standard (oltre 51 licenze)? –
Una specie di strana domanda (o un modo per chiederlo con specifico riferimento a FogBugz ...) ma non sono sicuro che sia necessario votare in basso ... – mmacaulay
Vedere l'OP [domanda precedente] (http://stackoverflow.com/questions/2684261/how-to-convert-a-number-to-a-range-of-prices). –