算法FogBugz的定价方案 [英] Algorithm for Fogbugz pricing scheme

查看:102
本文介绍了算法FogBugz的定价方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在寻找一种算法来计算的基础上的FogBugz为您的服务器的定价方案(http://www.fogcreek.com/FogBugz/PriceList.html)购买的许可证的总成本。

I'm looking for an algorithm to calculate total cost of licenses purchased based on the "FogBugz for your server" pricing scheme (http://www.fogcreek.com/FogBugz/PriceList.html).

FogBugz的定价是:

Fogbugz pricing is:

  • 1许可证$ 299
  • 5许可证包$ 999产品
  • 在10许可证包$ 1,899
  • 在20许可证包$ 3,499
  • 在50许可证包$ 7,999元

如果你问一个报价让我们说136的许可证,他们计算出它作为$二万二千六百九十四。

If you ask a quote for let's say 136 licenses they calculate it as $22,694.

我怎样才能做到这一点在C#或LINQ?

How can I do this in C# or LINQ?

任何帮助将AP preciated。

Any help will be appreciated.

推荐答案

接受的答案,而一个优雅的一块code从一个程序员的角度,不给最好的价格为客户,因此可能不是从客户的角度出发的一流解决方案。例如当n = 4,公认的答案给出了$ 1196,但客户会很明显preFER选择5许可证包和只付$ 999产品来代替。

The accepted answer, whilst an elegant piece of code from a programmer's point of view, does not give the best possible price for the customer and therefore might not be an elegant solution from the customer's point of view. For example when n = 4, the accepted answer gives $1196, but a customer would obviously prefer to choose the 5 license pack and pay just $999 instead.

有可能构造的算法可以计算客户可以支付购买他们所需的许可数目的最低的价格。这样做的一种方法是使用动态编程。我想,这样的事情可能做的伎俩:

It is possible to construct an algorithm which can calculate the minimum price possible that the customer can pay to purchase their required number of licenses. One way of doing this is to use dynamic programming. I think something like this might do the trick:

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));
}

输出:

22694
999


更新生产细分是有点复杂,但我绝对认为这将有利于你的客户。你可以做这样的事情(假设打印到控制台,但一个真正的方案很可能会输出到Web页面):


Update Producing a breakdown is a little more complicated, but I definitely think it will be beneficial for your customers. You could do it something like this (assuming printing to the console, although a real program would probably output to a web page):

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();
    }
}

输出:

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

这篇关于算法FogBugz的定价方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆