算法实例-关于旅行者的背包问题
基本问题:
0/1背包问题中,需要对容量为C的背包进行装载。从N个物品中选取装入背包的物品,每件物品I的重复为W(I),价值为P(I)。如何装入价值最大的物品?
算法:
贪心准则1-从剩余的物品中找出一个可以装入背包的价值最大的物品。
贪心准则2-从剩余的物品中找出可以装入背包的重量最小的物品。
贪心准则3-计算价值密度P(I)/W(I)。从剩余的物品中选择可装入包的P/W(I) 物品。
贪心算法之K阶优化-从答案中取出K件物品,并放入另外K件,获得的结果不会比原来的差。这样优化整个放入物品的序列。
动态规划-用递归进行计算求解。每一步求出基于现在状况下的最优解。(特点-计算复杂)
回溯算法-首先形成一个递归算法,去找到可获得的最大收益。即列出所有的候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找出所需要的解。(特点-候选解数量庞大)
变形问题:
·货郎的背包
·野外生存者的背包
·公司经理(?)的背包。
基本问题:
0/1背包问题中,需要对容量为C的背包进行装载。从N个物品中选取装入背包的物品,每件物品I的重复为W(I),价值为P(I)。如何装入价值最大的物品?
算法:
贪心准则1-从剩余的物品中找出一个可以装入背包的价值最大的物品。
贪心准则2-从剩余的物品中找出可以装入背包的重量最小的物品。
贪心准则3-计算价值密度P(I)/W(I)。从剩余的物品中选择可装入包的P/W(I) 物品。
贪心算法之K阶优化-从答案中取出K件物品,并放入另外K件,获得的结果不会比原来的差。这样优化整个放入物品的序列。
动态规划-用递归进行计算求解。每一步求出基于现在状况下的最优解。(特点-计算复杂)
回溯算法-首先形成一个递归算法,去找到可获得的最大收益。即列出所有的候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找出所需要的解。(特点-候选解数量庞大)
变形问题:
·货郎的背包
·野外生存者的背包
·公司经理(?)的背包。
解决方案 »
- 看看大家对jquery的看法!!!!!
- 弹出一个div的效果
- php 数据形式的转化
- php能够随时更新显示BT种子文件目前的“连接数”和“种子数”吗?
- 请教大家关于用php+mysql分页的思路和具体的一些例子..非常感谢!!
- 有谁用过PEAR里面的 LiveUser 吗?
- windows + php为什么不认QUERYSTRING,是否需要修改php.ini,怎么修改!?
- 在一个php中如何直接打开另一个php,详细一点
- 请问新建字段时候语句`aaa` varchar(11) NOT NULL,中的NOT NULL有什么作用呢?
- php socket服务端读取到客户端发送的数据 怎么把这个数据发送到html页面上
- 请问该规则如果重写rewrite
- 中英文混合字符如何转换大小写?
我这个问题比你这个还麻烦一些。
http://community.csdn.net/Expert/topic/4872/4872394.xml?temp=.7980463
1)你需要的是在有限空间里装入尽量多的文件
2)你需要在有限空间中装入价值量最大的尽量多的文件第一种情况的最优解很简单
解决方法很简单,把文件按照文件大小排序,然后从最小的开始往光盘上刻,这样可以保证在光盘里包含尽量多的文件第二种情况,解决方法不少,我给出我的
你的每个文件首先必须有他的价值属性(p),可能是星级或者别的什么,设文件大小为(s),则单位大小的价值(单价)为dp=p/s,你把文件按照dp由大到小排序,dp相同的文件,再根据s由小大排序,形成的序列就是你添加文件的顺序,如果添加某个文件后总大小超过大小限制则选择下一个单价下的第一个文件(下一个单价的最小文件)
'所有文件大小的数组。
Arr=array(200,300,350,80,20)''创建全局字典对象,用来存储所有得到的原子结果
Set dict=CreateObject("Scripting.Dictionary")Dim a(100)
strLength=ubound(Arr)+1
Dim best,spare,mass,aim
spare=700
aim=700For x=1 To strLength
a(0)=x
''计算5选1,5选2,5选5组合
combine strLength,x
next
sub combine(m, k)
''计算组合在m里面选k个元素的全部组合情况,添加到字典对象里
i=0
j=0
For i=m To k Step -1
a(k)=i
if (k>1) then
combine i-1,k-1
else
tempStr=""
mass=0
for j=1 To a(0)
tempStr=tempStr & a(j)
mass=mass+Arr(a(j)-1)
Next
if (aim-mass)<spare and mass<aim then
spare=aim-mass
best = tempStr
end if
''加到字典里
dict.add tempStr,mass
End if
next
End sub Main()Sub Main
''输出显示结果
For i=0 To dict.count-1
Document.write dict.keys()(i) & ":" & dict.items()(i) & "<br/>"
next
End sub
Document.write "最优方案:" & best & ":" & dict.item(best) & "<br/>"
</SCRIPT>
5:20
4:80
3:350
2:300
1:200
45:100
35:370
25:320
15:220
34:430
24:380
14:280
23:650
13:550
12:500
345:450
245:400
145:300
235:670
135:570
125:520
234:730
134:630
124:580
123:850
2345:750
1345:650
1245:600
1235:870
1234:930
12345:950
最优方案:235:670
就是选择第2个3个和5个文件。
danjiewu(阿丹)利用运筹学可以不必穷举。我上面的算法是穷举。如果有兴趣和时间可以搞一搞线性规划,就是需要查书找运筹学资料。
而且目前计算机速度解决这个问题,穷举不会感觉速度太慢,就无所谓了。
如果刚好n个文件,可以剪枝掉很多
例如,所有文件大小为a0,a1,a2,……,aM,都<=目标容量V
已经按照从小到大排序
之后就是DP了
先放a0
再对于0和a0分别放/不放a1,得到0,a0,a1,a0+a1四个解
再对于上面四个解分别放/不放a2,得到0,a0,a1,a2,a0+a1,a0+a2,a1+a2,a0+a1+a2八个解
……
也就是穷举所有的放/不放的组合
由于总容量V,复杂度为O(V*M)
如果限制了文件数n,当前已经考察了K个文件,对于某个包含k个文件的解s,连续取aK、aK+1、……直到取满n个文件(从文件K到文件K+(n-k-1)的容量和可以事先用O(n^2)得到),再看是否超出了V就可以了,超出的直接放弃
这样做确实有些操作是多余的。效率不好,空间占用也比较高。
下面是C#的语法。
====================================================using System;namespace Arith
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{ static UInt32 nLimit = 0;
static String result = String.Empty; /// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
String slist = string.Empty;
System.Text.RegularExpressions.Regex rexp = new System.Text.RegularExpressions.Regex(@"^(?:\d{1,4}[, -])+\d:\d{1,5}$"); do
{
Console.WriteLine("请输入(格式如:11,12,13,15,...,8,9:88):");
slist = Console.ReadLine();
}
while (!rexp.IsMatch(slist)); UInt32 nMax = UInt32.Parse(slist.Split(":".ToCharArray())[1]);
nLimit = nMax; String[] asList = slist.Split(":".ToCharArray())[0].Split(", -".ToCharArray());
System.Collections.ArrayList aList = new System.Collections.ArrayList(asList.Length); for (int i = 0; i < asList.Length; i++)
{
aList.Add(UInt32.Parse(asList[i]));
}
Console.WriteLine(nMax); for (int i = 0; i < aList.Count; i++)
{
GetLimit((UInt32)aList[i],nMax,aList.Clone() as System.Collections.ArrayList);
} Console.WriteLine("======================================");
Console.WriteLine(result);
Console.WriteLine("敲回车结束....");
Console.ReadLine();
} static void GetLimit(UInt32 baseVal, UInt32 maxVal, System.Collections.ArrayList alist)
{
UInt32 newMaxVal = maxVal-baseVal;
alist.Remove(baseVal); foreach (UInt32 al in alist)
{
if (newMaxVal==0)
{
nLimit = newMaxVal;
// result = String.Format("{0}\n{1}",result,GetString(alist));
}
if (nLimit == 0)
{
// ok.
return;
}
if (newMaxVal < nLimit)
{
nLimit = newMaxVal;
result = String.Format("{0}",GetString(alist));
}
if (newMaxVal < al)
{
// next
continue;
} GetLimit(al, newMaxVal, alist.Clone() as System.Collections.ArrayList); } // alist为空的时候就被落下来了。写的不好。
if (newMaxVal < nLimit)
{
nLimit = newMaxVal;
result = String.Format("{0}",GetString(alist));
} } static string GetString(System.Collections.ArrayList alist)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
alist.TrimToSize(); foreach(UInt32 al in alist)
{
sb.AppendFormat("{0} ",al);
} return sb.ToString();
}
}
}
--------------------------
gai:
(@"^(?:\d{1,4}[, -])+\d{1,4}:\d{1,5}$");
2.最近看了一下遗传算法,介绍说遗传算法很适合这类经典的最优解问题
3.如果规模小就遍历