装载问题和背包问题有些相似,但是又不完全一样。有n个集装箱,需要装入两艘轮船里面,每一艘轮船有自己的约束,希望把所有的集装箱全部装进去,有没有这样一种装法,都能够使的这些集装箱全部装到船上,进行合理的装载。
一、问题描述
问题:有n个集装箱,需要装上两艘载重分别为c1和c2的轮船. wi为第i个集装箱的重量,且 w 1 + w 2 + . . . + w n ≤ c 1 + c 2 w_1+w_2+...+w_n≤c_1+c_2 w1+w2+...+wn≤c1+c2
问:是否存在一种合理的装载方案把这n个集装箱装上船?如果有,请给出一种方案。
二、实例
这里有7个集装箱,第一艘船的约束重量是152,第二艘船的约束重量是130,只要能够全部装进去,那就是一种合理的装载方案。
W = < 90 , 80 , 40 , 30 , 20 , 12 , 10 > W=<90,80,40,30,20,12,10> W=<90,80,40,30,20,12,10>
c 1 = 152 , c 2 = 130 c_1=152, c_2=130 c1=152,c2=130
解: 1,3,6,7装第一艘船,其2,4,5装第二艘船
1、约束条件
这里没有求最小或者最大,这是和背包问题不同的,装载问题只要满足约束就好了。
2、解的形式
观察问题的解的形式,n个集装箱,每个集装箱要被装到船里面,无非是装到船一里面,或者装到船二里面,每个分量的选择就是0和1,如果用代码表示的话,可以这样去编码(PS:当然编码1和2也可以),这样的长度显然是n,大概我们要求的东西就是长度为1的n维向量,这个向量里面的取值就是0和1,0表示装在第一艘船里面,1表示装在第二艘船里面。
3、多米诺性质
接下来观察满不满足多米诺性质,如果拿出一部分向量来,如果这个时候已经破坏掉规则不满足约束了,船一或者船二的总重量已经超过了其载重量,这个时候再往上面再装,那肯定还是会破坏掉它的规则,只会越来越重,也就是说,部分向量如果已经不满足条件则增加维度的向量依然不满足约束条件,所以说装载问题满足多米诺性质。
三、求解思路
输 入 : W = < w 1 , w 2 , . . . , w n > 为 集 装 箱 重 量 c 1 和 c 2 为 船 的 最 大 载 重 量 算 法 思 想 : 令 第 一 艘 船 的 装 入 量 为 W 1 , 输入:W=<w_1,w_2, ..., w_n>为集装箱重量c_1和c_2为船的最大载重量 算法思想:令第一艘船的装入量为W_1, 输入:W=<w1,w2,...,wn>为集装箱重量c1和c2为船的最大载重量算法思想:令第一艘船的装入量为W1,
1、用回溯算法求使得 c 1 − W 1 c_1−W_1 c1−W1达到最小的装载方案.
2、 若满足条件
w 1 + w 2 + . . . + w n − W 1 ≤ c 2 w_1+w_2+...+w_n−W_1≤c_2 w1+w2+...+wn−W1≤c2
则回答“Yes”,否则回答“No”
clear
X=imread('lena.jpg');
data=uint8(X);
[zipped,info]=huffencode(data); %调用Huffman编码程序进行压缩
unzipped=huffdecode(zipped,info,data);
%调用Huffman编码程序进行解码
%显示原始图像和经编码后的图像,显示压缩比,并计算均方根误差得erms=0,表示是Huffman是无失真编码
subplot(121);imshow(data);
subplot(122);imshow(unzipped);
%erms=compare(data(:),unzipped(:))
cr=info.ratio
whos data unzipped zipped
function [zipped, info] = huffencode(vector)
% 输入和输出都是 uint8 格式
% info 返回解码需要的结构信息
% info.pad 是添加的比特数
% info.huffcodes 是 Huffman 码字
% info.rows 是原始图像行数
% info.cols 是原始图像列数
% info.length 是原始图像数据长度
% info.maxcodelen 是最大码长
if ~isa(vector, 'uint8')
error('input argument must be a uint8 vector');
end
[m, n] = size(vector);
vector = vector(:)';
f = frequency(vector); %计算各符号出现的概率
symbols = find(f~=0);
f = f(symbols);
[f, sortindex] = sort(f); %将符号按照出现的概率大小排列
symbols = symbols(sortindex);
len = length(symbols);
symbols_index = num2cell(1:len);
codeword_tmp = cell(len, 1);
% 生成 Huffman 树,得到码字编码表
while length(f)>1
index1 = symbols_index{
1};
index2 = symbols_index{
2};
codeword_tmp(index1) = addnode(codeword_tmp(index1), uint8(0));
codeword_tmp(index2) = addnode(codeword_tmp(index2), uint8(1));
f = [sum(f(1:2)),f(3:end)];
symbols_index = [{
[index1, index2]},symbols_index(3:end)];
[f, sortindex] = sort(f);
symbols_index = symbols_index(sortindex);
end
codeword = cell(256, 1);
codeword(symbols) = codeword_tmp;
len = 0;
for index = 1:length(vector) %得到整个图像所有比特数
len = len + length(codeword{
double(vector(index))+1});
end
string = repmat(uint8(0), 1, len);
pointer = 1;
for index = 1:length(vector) %对输入图像进行编码
code = codeword{
double(vector(index))+1};
len = length(code);
string(pointer + (0:len-1))=code;
pointer = pointer + len;
end
len = length(string);
pad = 8-mod(len, 8);
if pad > 0
string = [string uint8(zeros(1, pad))];
end
codeword = codeword(symbols);
codelen = zeros(size(codeword));
weights = 2.^(0:23);
maxcodelen = 0;
for index = 1:length(codeword)
len = length(codeword{
index});
if len > maxcodelen;
maxcodelen = len;
end
if len > 0
code = sum(weights(codeword{
index} == 1));
code = bitset(code, len + 1);
codeword{
index} = code;
codelen(index) = len;
end
end
codeword = [codeword{
:}];
%计算压缩的向量
cols = length(string)/8;
string = reshape(string, 8, cols);
weights = 2.^(0: 7);
zipped = uint8(weights * double(string));
%码表存储到一个希疏矩阵
huffcodes = sparse(1, 1);
for index = 1:nnz(codeword) % length(codeword) %numel(codeword)
huffcodes(codeword(index), 1) = symbols(index);
end
%填写解码时所需的结构信息
info.pad = pad;
info.huffcodes = huffcodes;
info.ratio = cols./length(vector);
info.length = length(vector);
info.maxcodelen = maxcodelen;
info.rows = m;
info.cols = n;
end
%函数addnode添加节点
function codeword_new = addnode(codeword_old, item)
codeword_new = cell(size(codeword_old));
for index = 1:length(codeword_old)
codeword_new{
index} = [item codeword_old{
index}];
end
end
%函数frequency计算各符号出现的概率
function f = frequency(vector)
if ~isa(vector, 'uint8')
error('input argument must be a uint8 vector');
end
f = repmat(0, 1, 256);
len = length(vector);
for index = 0:255
f(index+1) = sum(vector == uint8(index));
end
f = f./len; %归一化
end
function vector = huffdecode(zipped, info, image)
% 函数对输入矩阵vector进行Huffman解码,返回解压后的图像数据
if ~isa(zipped, 'uint8')
error('input argument must be be a uint8 vector');
end
%产生0,1序列,每位占一个字节
len = length(zipped);
string = repmat(uint8(0), 1, len.*8);
bitindex = 1:8;
for index = 1:len
string(bitindex + 8.*(index-1)) = uint8(bitget(zipped(index), bitindex));
end
string = logical(string(:)');
len = length(string);
string ((len-info.pad+1):end)=[];
len = length(string);
%开始解码
weights = 2.^(0:51);
vector = repmat(uint8(0), 1, info.length);
vectorindex = 1;
codeindex = 1;
code = 0;
for index = 1:len
code = bitset(code, codeindex, string(index));
codeindex = codeindex+1;
byte = decode(bitset(code, codeindex), info);
if byte > 0
vector(vectorindex) = byte-1;
codeindex = 1;
code = 0;
vectorindex = vectorindex + 1;
end
end
vector = reshape(vector, info.rows, info.cols);
end
%函数decode返回码字对应的符号
function byte = decode(code, info)
byte = info.huffcodes(code);
end