- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
记忆化搜索
妙用记忆化搜索解题例析
因为搜索太慢,所以超时了;因为动规太难,所以不编了。那么,这道题目就这样完了?如果可以,那么,我们就试试记忆化搜索。
题1
0/1 背包(package.pas)
【问题描述】
一个旅行者有一个最多能用 m 公斤的背包,现在有 n 件物品,它们的重量分别是 W1, W2,...,Wn,它们的价值分别为 C1,C2,...,Cn。若每种物品只有一件,求旅行者能获得最 大总价值。
【输入格】
第一行:两个整数,M(背包容量,M=200)和 N(物品数量,N=30); 第 2..N+1 行:每行二个整数 Wi,Ci,表示每个物品的重量和价值。
【输出格式】 仅一行,一个数,表示最大总价值。
【样例输入】package.in
10 4
2 1
3 3
4 5
7 9
【样例输出】package.out
12
【问题分析】
题目很经典,就是给你物品的重量和价值,叫你求最多用M单位的重量能获得的物品最大总价值。
【算法分析】
对于背包问题的动态转移方程和动规程序段大家都不陌生了:
for i:=1 to n do
for j:=m downto a[i] do
if f[j-a[i]]+b[i]f[j] then f[j]:=f[j-a[i]]+b[i];
(n代表物品数,m代表最大重量,a数组代表物品重量,b数组代表物品价值,f数组代表每个重量所能取得的最大价值)
那么,其实这道题目也可以用记忆化搜索来编,它的形式或许就是我们原本搜索的算法(时间复杂度为O(2^n),效率低下)的基础上加上2句语句就行了,但是,他的效率却与动规不相上下。
原本我们的搜索算法递归的变量是:还剩下重量j(也就是用了(m-j)的重量)并且还剩下前i个物品(也就是搜了(n-i)个物品(有的要了,有的没要))的价值,并且每次搜索分两种情况:1、此种物品不取,2、取此种物品(前提是剩下的重量要够取),然后我们在这两者间选最优值,即能获得的物品最大总价值。
那么在搜索的过程中,我们会重复计算I,j分别相同下的值。怎样优化呢?其实,现在只要用一个数组f[I,j]来存放此时搜索出来的I,j值(因为这个值保证最优,所以不需要再计算了),开始都赋值成-1,每次算相应的I,j的时候就记录下来,如果下次搜索时碰到一样的I,j的值,就不需要在重复求了。不要小看这一个“看似”不起眼的小小优化,其实此时我们的记忆化搜索的速度已经相当于动规了,而且数据小,可能还要快(因为动规要将每个重量所能取得的最大价值都算出来,而搜索只要算一部分)。
【参考程序】(记忆化搜索)
var f:array[0..30,0..10000] of longint;
w,v:array[1..30] of longint;
n,m,i,j:longint;
function max(a,b:longint):longint;
begin
if ab then exit(a) else exit(b);
end;
function get(i,j:longint):longint; {还剩下重量j并且还剩下前i个物品的价值}
var t:longint;
begin
if (i1) then exit(0); {如果此时已没有物品可取,就返回0}
if f[i,j]0 then {若对应的I,j没有求过}
begin
if jw[i] then t:=get(i-1,j) {取物品的重量不够,就不能取}
else t:=max(get(i-1,j),get(i-1,j-w[i])+v[i]);
{够,就在两者中选其最优值}
f[i,j]:=t; {记录算出的值}
end;
exit(f[i,j]); {返回最优值}
end;
begin
assign(input,package.in);
assign(output,package.out);
reset(input);rewrite(output);
readln(m,n);
for i:=1 to n do readln(w[i],v[i]);
fillchar(f,sizeof(f),255); {赋值成-1}
writeln(get(n,m)); {记忆化搜索}
close(input);close(output
文档评论(0)