有意思的题目
来源:互联网 发布:四九算法偶数是男 编辑:程序博客网 时间:2024/05/16 18:36
首先我承认我很无聊,不然不会干这个事
function result = Knapsack(Back_weight,Article)
globalarticle_mark;
globalarticle_result;
%Author:Q
�te:不详
�scribe:背包问题解法
%不同于普通的背包,这个函数解出的是符合背包的所有的解
%参数说明:
% 输入参数:
% Back_weight 背包容量
% Article 物品权重矩阵
%
% 输出参数:
% result 所有符合这个背包的解
[Lengthr,Lengthc]= size(Article);
article_mark= zeros(1,Lengthc);
article_result= [];
article_all_number= Lengthc ;
back_all_weight = Back_weight;
article = Article ;
article_number = 1;
back_weight = 0;
BackTrack(article_all_number,back_all_weight,article,article_number,back_weight);
result= article_result;
function result = BackTrack(article_all_number,back_all_weight,article,article_number,back_weight)
globalarticle_mark ;
globalarticle_result;
%Author:Q
�te:不详
�scribe:单个背包的递归函数
%参数说明:
% 输入参数:
% article_all_number 物品总数
% back_all_weight 背包还能装下的权重
% article 物品权重的矩阵
% article_number 当前背包中物品的数量
% back_weight 背包容量
%
% 输出参数:
% result 最外面的函数result = article_result;返回所有的递归结果
%
% 全局参数:
% article_mark 存放正在进行的标签
% article_result 存放符合的结果
ifarticle_number > article_all_number
judge_article_mark = article_mark;
judge_article_mark = judge_article_mark*article';
if sum(judge_article_mark) == back_all_weight
article_result = [article_result ; article_mark];
end
else
%没有等于的,但是有不大,不小的,所以剩下的就是只能是等号了
if back_weight + article(article_number) > back_all_weight
else
article_mark(article_number) = 1;
BackTrack(article_all_number,back_all_weight,article,article_number + 1,back_weight + article(article_number));
end
article_mark(article_number) = 0;
if bound_weight(article_number + 1,article) < back_all_weight - back_weight
else
BackTrack(article_all_number,back_all_weight,article,article_number + 1,back_weight);
end
end
function result = bound_weight(number,article)
%Author:Q
�te:不详
�scribe:就是个背包的家和函数
%当时好像是不想用matlab自带的,所以自己写了一个
%参数说明:
% 输入参数:
% number 标记,记录是不是被装入背包
% article 每个物品的权重
%
% 输出参数:
% result 家和的结果
[Lengthr,Lengthc]= size(article);
sum= 0;
form = number:Lengthc
sum =sum + article(m);
end
result= sum;
这个程序的作用是找出背包问题所有的解法
clear all
clc
weight= 15;
article= [9 6 4 2];
resutl= Knapsack(weight,article);
resutl
运行结果:
clear all
clc
k= 3; %找出k个数
article= [9 6 4 2]; %n个数
weight= 16; %和为m
judge= 0;
upvalue= 0;
downvalue= 0;
result= [];
whilejudge == 0
tmpweight1 = weight + upvalue;
resutl1 = Knapsack(tmpweight1,article);
[row1 column1] = size(resutl1);
if row1 == 0
else
tmpjudge1 = 0;
for i = 1:row1
if (sum(resutl1(i,:)) == k) %发现符合条件的
tmpjudge1 = 1;
result = resutl1(i,:);
end
end
今天被人问了个问题,觉的很有意思,就做了一下。发现确实有意思。
题目是:给你n个数,然后找出k个数,是的这k个数的和最接近m
细想了一下这就是个背包问题的变种。
但是很普通的背包问题又不同,因为一般背包问题一般就一个解,而且对物品的数量没限制(选多少随便你)。这个是定死了是K个,所以就是要求装背包,然后还要求物品数量是K。
我想的解答过程是,先就是普通的背包解法,因为普通的背包会有很多个解答,但是肯定又一个解答是K(这个不一定有K个的,之后会详说),这个K的解答就是这个问题的答案。
所以第一步就是做一个可以解出所有解答的背包问题的解答。
这用动态规划法+减枝 借这个背包问题(不明白什么意思的自己去看书)
程序分成三个文件
Knapsack.m
global
global
%Author:Q
�te:不详
�scribe:背包问题解法
%不同于普通的背包,这个函数解出的是符合背包的所有的解
%参数说明:
%
%
%
%
%
%
[Lengthr,Lengthc]
article_mark
article_result
article_all_number
back_all_weight
article
article_number
back_weight
BackTrack(article_all_number,back_all_weight,article,article_number,back_weight);
result
BackTrack.m
global
global
%Author:Q
�te:不详
�scribe:单个背包的递归函数
%参数说明:
%
%
%
%
%
%
%
%
%
%
%
%
%
if
else
end
bound_weight.m
%Author:Q
�te:不详
�scribe:就是个背包的家和函数
%当时好像是不想用matlab自带的,所以自己写了一个
%参数说明:
%
%
%
%
%
%
[Lengthr,Lengthc]
sum
for
end
result
例如:
背包容量 weight =15;
物品质量 article = [9 6 4 2];
这个有两解答
9 + 6 = 15
9 + 4 + 2 = 15
测试例子:
clc
weight
article
resutl
resutl
每一行是一个结果,为1表示选中
回到刚刚的问题,如果K = 3,那么就是找3个数,那么第一行就是不符合结果的。
那么第二行就是解答。
所以有一个循环可以找1的数目,那么这个问题就算解决了。
但是这个问题还有一个条件,他是找最接近M的,并不是等于M的,所以可能得到的结果是个空集
解决这个问题的就是以当前的M为中心,左右找点,去用刚刚的这个方法去试,如果有解答,那么这个解答就是最接近的解答。。
所以最后来一左右点寻找的循环就可以了
clc
k
article
weight
judge
upvalue
downvalue
result
while