在根据总用量计算每种包装规格的购买量和总价 中讲述了一个开发的场景,首先有一个总共的土地拥有量:total亩,现在有n种可以选择的商品,每一种商品都有每亩的用量:amount/亩,每一种商品都有多个包装规格,每个包装规格有自己的包装量和售价。
需求就是计算出,在给定土地上面种植那种商品需要的花费最少,也就是可以用最少的钱来买更多的东西种地,满足我种地的最大需求量。
其实我们还假设了一个前提,就是包装大的单价低,好比100克每包的可能买100元,200克每包的就应该卖180元,肯定会小于两个100克每包的价格,这个也是市场调研的结果,也比较符合市场常规。
代码中用到了二分搜索法的思路,其实我需要的是一个定位,定位我需要购买的最合算的包装规格,也就是在满足需要的情况下,尽可能购买大包装。
例如:现在有两个商品,土豆和白菜,土豆有三个规格,100克每包的100元,200克每包的180元,300克每包的240元;白菜有四个规格,100克每包的70元,200克每包的130元,300克每包的200元,400克每包的300元。种白菜每亩要100斤,中土豆每亩尧200斤。我总共有1029亩地,计算一下,是种土豆花费少?还是种白菜花费少?
有两个点要注意:1)找位置,找到我需要购买的最合算的包装规格的位置,使用了二分搜索2)计算用量和预算。
计算一种商品最少花费的伪代码如下:
输入:一个商品的信息,包括包装规格
输出:需要购买的包装规格几个数,总共的花费
计算过程:
{
while(总量>最小包装规格的量)
{
1)找位置,定位包装规格
2)计算需要购买多少个第一步找到的包装规格
3)需要购买的个数=总量和包装规格的包装量取整
4)总量=总量-需要购买的个数*包装规格的包装量
5)这种商品的预算+=需要购买的个数*包装规格的单价
}
if(总量<=最小包装规格的量)
{
说明零头就只能买个最小包装了,因为购买不支持散买。
}
}
示例代码下载:/Files/virusswb/BeautyCode.ConApp.rar
代码如下:
* Created by SharpDevelop.
* User: haier
* Date: 2010-3-23
* Time: 22:19
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
namespace BeautyCode.ConApp
{
/// <summary>
/// 种植方案
/// </summary>
public class PlantArea
{
/// <summary>
/// 种植面积,单位是亩
/// </summary>
public static decimal PlantAreaAmount = 175.25m ;
}
/// <summary>
/// 商品类型
/// </summary>
public enum ProductType
{
/// <summary>
/// 种子
/// </summary>
Seed,
/// <summary>
/// 肥料
/// </summary>
Fertilizer,
/// <summary>
/// 农药
/// </summary>
Pesticide
}
public enum FertType
{
/// <summary>
/// 底肥
/// </summary>
DiF,
/// <summary>
/// 种肥
/// </summary>
ZhongF,
/// <summary>
/// 追肥
/// </summary>
ZhuiF
}
public class Unit
{
public Guid ID{ set ; get ;}
public string CnName{ set ; get ;}
}
public class PkgPrice
{
public Guid PkgID{ set ; get ;}
/// <summary>
/// 包装量
/// </summary>
public decimal PkgAmount{ set ; get ;}
/// <summary>
/// 包装单位
/// </summary>
public Unit PkgUnit{ set ; get ;}
/// <summary>
/// 包装价格
/// </summary>
public decimal Price{ set ; get ;}
/// <summary>
/// 选中的包装个数
/// </summary>
public int Quantities{ set ; get ;}
}
public class Product
{
public virtual Guid ID{ set ; get ;}
public virtual string Name{ set ; get ;}
public virtual ProductType ProType{ set ; get ;}
/// <summary>
/// 每亩用量
/// </summary>
public virtual decimal Amount{ set ; get ;}
/// <summary>
/// 每亩用量单位
/// </summary>
public virtual Unit ProductUnit{ set ; get ;}
/// <summary>
/// 总用量
/// </summary>
public virtual decimal TotalAmount{ set ; get ;}
public Product (ProductType type)
{
this .ProType = type;
}
/// <summary>
/// 预算
/// </summary>
public decimal Budget{ set ; get ;}
/// <summary>
/// 全部包装类型
/// </summary>
public List < PkgPrice > AllPkgPrice{ set ; get ;}
/// <summary>
/// 选中的包装类型
/// </summary>
public List < PkgPrice > SelectPkgPrice{ set ; get ;}
}
public class Seed:Product
{
public Seed (): base (ProductType.Seed ){}
public List < Pesticide > Pesticides{ set ; get ;}
public List < DiF > DiFs{ set ; get ;}
public List < ZhongF > ZhongFs{ set ; get ;}
public List < ZhuiF > ZhuiFs{ set ; get ;}
}
public class Fertilizer:Product
{ public FertType FType{ set ; get ;}
public Fertilizer (FertType type): base (ProductType.Fertilizer){
this .FType = type ;
}
}
public class DiF:Fertilizer
{
public DiF (): base (FertType.DiF ){}
}
public class ZhongF:Fertilizer
{
public ZhongF (): base (FertType .ZhongF ){}
}
public class ZhuiF:Fertilizer
{
public ZhuiF (): base (FertType.ZhuiF ){}
}
public class Pesticide:Product
{
public Pesticide (): base (ProductType.Pesticide ){}
}
/// <summary>
/// Description of BeiBao.
/// </summary>
public class BeiBao
{
public List < Seed > Seeds = null ;
public Seed Seed = null ;
public List < Pesticide > Pesticides = null ;
public Pesticide Pesticide = null ;
public List < DiF > DiFs = null ;
public DiF DiF = null ;
public List < ZhongF > ZhongFs = null ;
public ZhongF ZhongF = null ;
public List < ZhuiF > ZhuiFs = null ;
public ZhuiF ZhuiF = null ;
public List < PkgPrice > PkgPrices = null ;
public BeiBao()
{
Seeds = new List < Seed > ();
Seed = new Seed(){ ID = Guid.NewGuid (),
Name = " 土豆 " , Amount = 120 , Budget = 0 ,
TotalAmount = 120 * PlantArea.PlantAreaAmount };
PkgPrices = new List < PkgPrice > (){
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 100 , Price = 23 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 210 , Price = 58 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 130 , Price = 39 }};
Seed .AllPkgPrice = PkgPrices ;
Seed.AllPkgPrice.Sort( new Comparison < PkgPrice > (comparePkgAmountAsc));
Seeds.Add(Seed );
Seed = new Seed(){ ID = Guid.NewGuid (),
Name = " 白菜 " , Amount = 150 , Budget = 0 , TotalAmount = 150 * PlantArea.PlantAreaAmount };
PkgPrices = new List < PkgPrice > (){
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 80 , Price = 20 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 180 , Price = 48 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 110 , Price = 34 }};
Seed .AllPkgPrice = PkgPrices ;
Seed.AllPkgPrice.Sort( new Comparison < PkgPrice > (comparePkgAmountAsc));
Seeds.Add(Seed );
Seed = new Seed(){ ID = Guid.NewGuid (),
Name = " 萝卜 " , Amount = 100 , Budget = 0 , TotalAmount = 100 * PlantArea.PlantAreaAmount };
PkgPrices = new List < PkgPrice > (){
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 110 , Price = 35 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 250 , Price = 79 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 170 , Price = 49 }};
Seed .AllPkgPrice = PkgPrices ;
Seed.AllPkgPrice.Sort( new Comparison < PkgPrice > (comparePkgAmountAsc));
Seeds.Add(Seed );
Seed = new Seed(){ ID = Guid.NewGuid (),
Name = " 大豆 " , Amount = 20 , Budget = 0 , TotalAmount = 20 * PlantArea.PlantAreaAmount };
PkgPrices = new List < PkgPrice > (){
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 110 , Price = 35 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 250 , Price = 79 },
new PkgPrice (){ PkgID = Guid.NewGuid (),PkgAmount = 170 , Price = 49 }};
Seed .AllPkgPrice = PkgPrices ;
Seed.AllPkgPrice.Sort( new Comparison < PkgPrice > (comparePkgAmountAsc));
Seeds.Add(Seed );
}
public Product ComputeOptimized()
{
foreach (Product p in this .Seeds )
{
GetTotalBudget ( p);
}
Seeds.Sort ( new Comparison < Seed > (compareProductBudgetAsc ));
return Seeds[ 0 ];
}
private void GetTotalBudget(Product p)
{
p.SelectPkgPrice = new List < PkgPrice > ();
int index =- 1 ;
int quantities = 0 ;
decimal totalamount = p.TotalAmount;
while (totalamount > p.AllPkgPrice [ 0 ].PkgAmount )
{
index = binaryLocalize (p.AllPkgPrice,totalamount,p.AllPkgPrice.Count );
if (index !=- 1 )
{
quantities = ( int )(totalamount / p.AllPkgPrice [index ].PkgAmount );
// quantities =(int)(totalamount %p.AllPkgPrice [index ].PkgAmount );
p.SelectPkgPrice.Add( new PkgPrice (){
PkgID = p.AllPkgPrice[index].PkgID ,
PkgAmount = p.AllPkgPrice[index].PkgAmount,
Price = p.AllPkgPrice[index].Price ,
Quantities = quantities
});
p.Budget += quantities * p.AllPkgPrice[index].Price ;
}
totalamount -= quantities * p.AllPkgPrice[index].PkgAmount;
}
if (totalamount != 0 )
{
quantities = 1 ;
index = 0 ;
p.SelectPkgPrice.Add( new PkgPrice (){
PkgID = p.AllPkgPrice[index].PkgID ,
PkgAmount = p.AllPkgPrice[index].PkgAmount,
Price = p.AllPkgPrice[index].Price ,
Quantities = quantities
});
p.Budget += quantities * p.AllPkgPrice[index].Price ;
}
}
/// <summary>
/// 二分法搜索元素
/// </summary>
/// <param name="a"></param>
/// <param name="x"></param>
/// <param name="n"></param>
/// <returns></returns>
private int binarySearch(List < int > a, int x, int n)
{
int left = 0 ;
int right = n - 1 ;
while (left <= right)
{
int middle = (left + right ) / 2 ;
if (x == a[middle]) return middle;
if (x > a[middle ])left = middle + 1 ;
else right = middle - 1 ;
}
// 没有找到
return - 1 ;
}
/// <summary>
/// 二分法定位规格
/// </summary>
/// <param name="pkgPrices"></param>
/// <param name="totalAmount"></param>
/// <param name="n"></param>
/// <returns></returns>
private int binaryLocalize(List < PkgPrice > pkgPrices, decimal totalAmount, int n)
{
if (totalAmount >= pkgPrices [n - 1 ].PkgAmount )
return n - 1 ;
int left = 0 ;
int right = n - 1 ;
while (left <= right )
{
int middle = (left + right ) / 2 ;
if (totalAmount >= pkgPrices [middle ].PkgAmount && totalAmount < pkgPrices [middle + 1 ].PkgAmount )
{
return middle ;
}
if (totalAmount == pkgPrices [middle + 1 ].PkgAmount )
{
return middle + 1 ;
}
if (totalAmount > pkgPrices [middle + 1 ].PkgAmount )
left = middle + 1 ;
else
right = middle - 1 ;
}
return - 1 ;
}
private int compareProductBudgetAsc(Product pro1,Product pro2)
{
if (pro1.Budget > pro2 .Budget )
return 1 ;
if (pro1.Budget < pro2 .Budget )
return - 1 ;
else
return 0 ;
}
private int comparePkgAmountAsc(PkgPrice pkg1,PkgPrice pkg2)
{
if (pkg1.PkgAmount > pkg2.PkgAmount )
return 1 ;
if (pkg1.PkgAmount < pkg2 .PkgAmount )
return - 1