- 论坛徽章:
- 89
|
本帖最后由 fender0107401 于 2014-09-02 12:37 编辑
写在前面:本帖所产生的任何法律问题与本人无关。我只是写了点代码测试了一下,然后发个贴,仅此而已。
简单的说吧,cobras对比了一下“动态规划”和“贪心算法”在求解背包问题的对比。
详见:http://bbs.chinaunix.net/thread-4152274-1-1.html 的12楼。
他的结论跟我的差不多,贪心算法在绝大多数情况下能得到最优解。
我弄了2个版本的,一个是Matlab的,一个是C++的,时间仓促,都不敢保证没有逻辑错误。
Matlab的花了1个小时实现,C++的花了2个小时。
注:完全自己实现,没有任何抄袭。
简单的验证了一下,没有做太多的测试。
以前也没玩过这个东西,所以百度了一下,主要参考的这个,完全现学现卖,没有任何深入思考。
http://blog.csdn.net/mu399/article/details/7722810
这个写的还挺清楚的,不过就是貌似作者把表给弄颠倒了。。。。
这个算法就跟下雨差不多,从左到右,从上到下(不用从下到上,那个写博客的人是从下到上弄的,不过给出的递推公式应该是从上到下的),本质就是生产一张表,所以空间复杂度是2次方的,所以规模一大就超级慢,而且Matlab版的代码会直接告诉你内存不足。。。
先贴个Matlab的实现(对错不敢保证,因为没玩过,而且也没有太多的测试,而且花费的时间也比较少):
这个是main_01.m用来测试,就是算上面的博客里面提供的那个问题,需要去掉dp_solver.m最后面的%disp(table)的注释。
- item_w = [4, 5, 6, 2, 2];
- item_v = [6, 4, 5, 3, 6];
- tc = 10;
- tv_01 = dp_solver(item_w, item_v, tc);
- tv_02 = gr_solver(item_w, item_v, tc);
- disp(tv_01);
- disp(tv_02);
复制代码 这个是main_02.m可以用来对比两个算法的性能,动态规划会越算越慢,贪心算法就非常节省资源,毕竟主要的东西就是排序,所以时间和空间复杂度就等于使用排序算法的对应值。
clc; clear; close;
test_size = 2000;
time_cost = zeros(2, test_size);
performance = zeros(2, test_size);
pr = zeros(1, test_size);
termination_number = 10 * test_size;
tmp_index = 1;
for index= 10:10:termination_number
disp(tmp_index);
[item_w, item_v, tc] = generate_test_model(index);
tic; performance(1, tmp_index) = dp_solver(item_w, item_v, tc); time_cost(1, tmp_index) = toc / 1;
tic; performance(2, tmp_index) = gr_solver(item_w, item_v, tc); time_cost(2, tmp_index) = toc / 1;
tmp_index = tmp_index + 1;
end
disp(time_cost);
disp(performance);
for index = 1:1:test_size
tmp_01 = performance(1, index);
tmp_02 = performance(2, index);
pr(1, index) = (tmp_01 - tmp_02) / tmp_01;
end
tmp_size = 0;
[~, tmp_size] = size(pr(pr > 0.05));
disp('The pr size is:')
disp(tmp_size);
这个是生成测试问题的函数generate_test_model.m,如果想测试其他的随机数或者是tc(我试过2和1.5乘以物品数量)的值,可以在这里面改。- function [item_w, item_v, tc] = generate_test_model(problem_size)
- item_v = ceil(10 * rand(1, problem_size));
- item_w = ceil(10 * rand(1, problem_size));
-
- %item_v = abs(ceil(10 * randn(1, problem_size))) + 1;
- %item_w = abs(ceil(10 * randn(1, problem_size))) + 1;
- tc = ceil(problem_size * 1.5);
- end
复制代码 这个是动态规划的计算函数:dp_solver.m- function tv = dp_solver(item_w, item_v, tc)
-
- [~, item_number] = size(item_w);
-
- table = zeros(item_number, tc);
-
- for index_j = 1:1:tc
- for index_i = 1:1:item_number
- tmp_w = item_w(index_i);
- tmp_v = item_v(index_i);
- tmp_01 = 0;
- tmp_02 = 0;
-
- if ((index_j - tmp_w) >= 0)
- if (((index_i - 1) > 0) && ((index_j - tmp_w) > 0))
- tmp_01 = table((index_i - 1) , (index_j - tmp_w)) + tmp_v;
- else
- tmp_01 = tmp_v;
- end
- end
-
- if ((index_i - 1) > 0)
- tmp_02 = table((index_i - 1), (index_j));
- end
-
- table(index_i, index_j) = max(tmp_01, tmp_02);
- end
- end
-
- tv = table(item_number, tc); %disp(table);
- end
复制代码 这个是贪心算法的计算函数:gr_solver.m- function tv = gr_solver(item_w, item_v, tc)
- [~, item_number] = size(item_w);
-
- tv = 0; % tv
- w = 0; % the initial weight
- v = 0; % the initial value
-
- item_r_old = zeros(1, item_number);
- result_array = zeros(1, item_number);
-
- for index = 1:1:item_number
- item_r_old(index) = item_v(index) / item_w(index);
- end
-
- [~, index_array] = sort(item_r_old, 'descend');
-
- for index = 1:1:item_number
- item_index = index_array(index);
- v = v + item_v(item_index);
- w = w + item_w(item_index);
-
- if (w > tc)
- break;
- else
- result_array(index) = item_index;
- tv = tv + item_v(item_index);
- end
- end
- end
复制代码 用上述代码,计算上面的博客重的问题,可以生成下述的表。- tv = table(item_number, tc); %disp(table);
复制代码 默认是不输出表的,需要手工把dp_solver.m里面的上面一行里面的后面那块的注释去掉,也就是下面的样子。- tv = table(item_number, tc); disp(table);
复制代码 0 0 0 6 6 6 6 6 6 6
0 0 0 6 6 6 6 6 10 10
0 0 0 6 6 6 6 6 10 11
0 3 3 6 6 9 9 9 10 11
0 6 6 9 9 12 12 15 15 15
运行main_02会发现(下面的结果是用test_size = 100算的)下面的结果,程序会输出每次的计算时间和最有的目标函数值。
最后的pr是性能的比值,具体定义是在所有计算结果中,贪心算法和动态规划的结果差距较大的实验次数,比如下面的输出就是1次,也就是说100次实验里面,只有1次差距较大。
此处,差距较大是说同样的模型两者计算结果相差超过5%。
首先输出的是计算时间对比,上面的是动态规划的,下面的是贪心算法的。从结果上看,贪心算法完胜,哈哈。
Columns 1 through 11
0.0101 0.0002 0.0003 0.0005 0.0009 0.0011 0.0018 0.0021 0.0026 0.0032 0.0039
0.0017 0.0001 0.0001 0.0001 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002 0.0002
Columns 12 through 22
0.0045 0.0053 0.0062 0.0066 0.0077 0.0067 0.0077 0.0106 0.0121 0.0097 0.0093
0.0003 0.0003 0.0003 0.0003 0.0003 0.0002 0.0002 0.0003 0.0003 0.0003 0.0003
Columns 23 through 33
0.0102 0.0108 0.0114 0.0123 0.0132 0.0153 0.0153 0.0163 0.0174 0.0193 0.0197
0.0002 0.0002 0.0002 0.0002 0.0002 0.0003 0.0003 0.0003 0.0003 0.0003 0.0003
Columns 34 through 44
0.0222 0.0248 0.0240 0.0255 0.0306 0.0285 0.0322 0.0333 0.0354 0.0363 0.0379
0.0003 0.0003 0.0005 0.0003 0.0003 0.0003 0.0003 0.0003 0.0003 0.0003 0.0003
Columns 45 through 55
0.0385 0.0448 0.0466 0.0437 0.0580 0.0597 0.0540 0.0524 0.0517 0.0537 0.0551
0.0003 0.0009 0.0003 0.0003 0.0004 0.0003 0.0003 0.0004 0.0004 0.0004 0.0004
Columns 56 through 66
0.0605 0.0655 0.0666 0.0670 0.0676 0.0601 0.0652 0.0664 0.0704 0.0730 0.0756
0.0004 0.0004 0.0004 0.0004 0.0004 0.0004 0.0004 0.0003 0.0004 0.0007 0.0004
Columns 67 through 77
0.0744 0.0763 0.0740 0.0745 0.0737 0.0767 0.0810 0.0813 0.0833 0.0852 0.0872
0.0004 0.0004 0.0003 0.0004 0.0004 0.0004 0.0004 0.0004 0.0004 0.0004 0.0004
Columns 78 through 88
0.0915 0.0974 0.1000 0.1013 0.1038 0.1070 0.1076 0.1052 0.1109 0.1137 0.1164
0.0004 0.0008 0.0008 0.0004 0.0004 0.0004 0.0004 0.0004 0.0004 0.0004 0.0004
Columns 89 through 99
0.1207 0.1259 0.1242 0.1299 0.1354 0.1320 0.1605 0.1867 0.1298 0.1351 0.1366
0.0004 0.0004 0.0004 0.0004 0.0004 0.0004 0.0006 0.0008 0.0005 0.0004 0.0004
Column 100
0.1269
0.0004
然后是计算结果对比,上面的是动态规划的,下面的是贪心算法的,基本上,多数清楚下,两者差不多。
Columns 1 through 9
29 58 90 134 147 222 208 266 322
29 58 89 127 144 222 207 263 318
Columns 10 through 18
301 346 334 413 398 472 529 502 548
301 344 332 413 393 470 529 496 541
Columns 19 through 27
643 688 637 721 783 696 812 793 834
643 681 637 721 782 695 812 789 834
Columns 28 through 36
880 949 927 1008 1015 1041 1078 1021 1160
878 945 923 1006 1011 1036 1074 1013 1160
Columns 37 through 45
1212 1228 1168 1293 1242 1334 1300 1270 1500
1210 1223 1166 1286 1239 1328 1294 1264 1496
Columns 46 through 54
1426 1491 1528 1534 1543 1676 1645 1675 1772
1426 1490 1523 1527 1540 1676 1639 1673 1771
Columns 55 through 63
1811 1789 1739 1796 1861 1952 1944 2011 1991
1810 1789 1736 1790 1860 1949 1937 2008 1985
Columns 64 through 72
2101 2091 2042 2055 2198 2209 2272 2210 2255
2100 2087 2039 2050 2193 2205 2269 2208 2253
Columns 73 through 81
2247 2413 2263 2317 2470 2475 2444 2558 2505
2241 2407 2263 2312 2468 2473 2443 2555 2499
Columns 82 through 90
2609 2597 2581 2709 2726 2755 2788 2673 2701
2604 2593 2580 2707 2725 2753 2784 2672 2695
Columns 91 through 99
2891 2892 2901 3063 2897 3197 2930 3028 3175
2884 2885 2895 3059 2894 3192 2927 3028 3173
Column 100
3188
3186
The pr size is:
1 |
|