通过Pisinger快速解决方案,以子集和算法

编程入门 行业动态 更新时间:2024-10-13 18:27:12
本文介绍了通过Pisinger快速解决方案,以子集和算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

这是一个后续行动,我的previous 问题。我仍然觉得很有意思的问题,因为有一个算法,值得更多的关注,我在这里张贴。

从维基百科:对于每一个喜的情况下是积极的,受限于相同的恒定,Pisinger发现了一个线性时间的算法。的

有一个不同的纸张,这似乎说明了同样的算法,但它是一个有点难以阅读对我来说,所以请 - 没有人知道怎么翻译,从第4页( balsub )进入工作实施?

下面是几个指针我收集迄今:

www.diku.dk/~pisinger/95-6。 PS (纸) stackoverflow/a/9952759/1037407 www.diku.dk/hjemmesider/ansatte/pisinger/ codes.html

PS:我真的不坚持precisely这个算法,因此,如果您知道任何其他类似的高性能算法,请随时提出它吼叫

修改

这是的code一个Python版本贴娄由oldboy:

类视图(对象):     高清__init __(个体经营,序列,开始):         self.sequence,self.start =序列,开始     高清__getitem __(个体经营,指数):         回报self.sequence [指数+ self.start]     高清__setitem __(个体经营,指数值):         self.sequence [指数+ self.start] =价值 高清balsub(W,C):     '''均衡算法由大卫Pisinger子集和问题     W精品背包'''的=权重,C =容量     N = LEN(W)     断言N'GT; 0     sum_w = 0     使r = 0     对于WJ在W:         断言WJ> 0         sum_w + = WJ         断言WJ< = C         R = MAX(R,WJ)     断言sum_w> C     B = 0     w_bar = 0     而w_bar + W [B]< = C:         w_bar + =瓦特并[b]         B + 1 =     S = [[0] * 2 *在范围r为I(N - B + 1)]     s_b_1 =视图(S [0],R - 1)     对于在范围亩(-R + 1,1):         s_b_1 [μ= -1     对于在范围亩(1,R + 1):         s_b_1 [μ= 0     s_b_1 [w_bar - C] = B     在t范围内(B,N):         s_t_1 =视图(S [T - B],R - 1)         S_T =视图(S [T - B + 1],R ​​ - 1)         对于在范围亩(-R + 1,R + 1):             S_T微米= s_t_1微米         对于在范围亩(-R + 1,1):             mu_prime =亩+ W [T]             S_T [mu_prime] = MAX(S_T [mu_prime],s_t_1μ)         对于在范围亩(瓦特[吨],0,-1):             对于j的范围(S_T微米 - 1,s_t_1微米 - 1,-1):                 mu_prime =亩 - W [J]。                 S_T [mu_prime] = MAX(S_T [mu_prime],J)     解决=假     Z = 0     s_n_1 =视图(S [N - B],R - 1)     而Z取代; = -r + 1:         如果s_n_1 [Z]≥= 0:             解决= TRUE             打破         ž - = 1     如果解决:         打印Ç+ Z         打印传单N         X = [虚假] * N         对于j在范围(0,b)的             X [J] = TRUE         在t在范围(N - 1,B - 1,-1):             S_T =视图(S [T - B + 1],R ​​ - 1)             s_t_1 =视图(S [T - B],R - 1)             而真正的:                 J = S_T [Z]                 断言J> = 0                 z_unprime = Z + W [J]。                 如果z_unprime> R或J> = S_T [z_unprime]:                     打破                 Z = z_unprime                 X [J] = FALSE             z_unprime = Z - W [T]             如果z_unprime&GT = -r + 1和s_t_1 [z_unprime]≥= S_T [Z]:                 Z = z_unprime                 X [T] = TRUE         对于j的范围(n)的:             打印X [J],W [J]。

解决方案

//输入: // C(背包的容量) // N(件数) // W_1(重量项目1) // ... // w_n(重量项的n) // //输出: // Z(最优解) //ñ // X_1(指标为第1项) // ... // x_n(指标项目N) #包括<算法> #包括<&了cassert GT; #包括<的iostream> #包括<载体> 使用名字空间std; 诠释的main(){   INT C = 0;   CIN>> C;   INT N = 0;   CIN>> N;   断言(正大于0);   矢量< int的> W(N);   INT sum_w = 0;   INT R = 0;   为(诠释J = 0; J&n种++ j)条{     CIN>> W [J]。     断言(W [J]大于0);     sum_w + = W [J]。     断言(W [J]< = C);     R = MAX(R,W [J]);   }   断言(sum_w> C);   INT B:   INT w_bar = 0;   对于(B = 0; w_bar + W [B]< = C ++ B){     w_bar + =瓦特并[b];   }   矢量<矢量< INT> > S(N - B + 1,矢量< INT>(2 * R));   矢量< INT>:迭代s_b_1 = S [0] .begin()+(R - 1);   对于(INT亩= -r + 1;万亩< = 0; ++亩){     s_b_1 [μ= -1;   }   对于(INT亩= 1;万亩< = R ++亩){     s_b_1 [μ= 0;   }   s_b_1 [w_bar - C] = B;   对于(INT T = B:T&n种++ T){     矢量< INT> ::为const_iterator s_t_1 = S [吨 - B] .begin()+(R - 1);     矢量< INT> :: S_T =迭代器[吨 - B + 1] .begin()+(R - 1);     对于(INT亩= -r + 1;万亩< = R ++亩){       S_T微米= s_t_1微米;     }     对于(INT亩= -r + 1;万亩< = 0; ++亩){       INT mu_prime =亩+ W [T]       S_T [mu_prime] =最大值(S_T [mu_prime],s_t_1μ);     }     对于(INT亩= W [T];万亩> = 1; --mu){       对于(INT J = S_T微米 - 1; J> = s_t_1微米; --j){         INT mu_prime =亩 - W [J]。         S_T [mu_prime] = MAX(S_T [mu_prime],J);       }     }   }   布尔解决= FALSE;   INT Z者除外;   矢量< INT> ::为const_iterator s_n_1 = S [N - B] .begin()+(R - 1);   对于(Z = 0; Z取代; = -r + 1; --z){     如果(s_n_1 [Z]≥= 0){       解决= TRUE;       打破;     }   }   如果(解决){     COUT<< C + z,其中;< '\ N'<< N'LT;< '\ N';     矢量<布尔> X(N,FALSE);     对于(INT J = 0; J< B; ++ j)条X [J] =真;     对于(INT T = N - 1; T> = B; --t){       矢量< INT> :: S_T = S为const_iterator [吨 - B + 1] .begin()+(R - 1);       矢量< INT> ::为const_iterator s_t_1 = S [吨 - B] .begin()+(R - 1);       而(真){         INT J = S_T [Z]。         断言(J> = 0);         INT z_unprime = Z + W [J]。         如果(z_unprime> R || J&G​​T; = S_T [z_unprime])破;         Z = z_unprime;         X [J] = FALSE;       }       INT z_unprime = Z - W [T];       如果(z_unprime&GT = -r +1安培;&安培; s_t_1 [z_unprime]≥= S_T [Z]){         Z = z_unprime;         X [T] =真;       }     }     为(诠释J = 0; J&n种++ j)条{       COUT<< X [J]<< '\ N';     }   } }

This is a follow-up to my previous question. I still find it very interesting problem and as there is one algorithm which deserves more attention I'm posting it here.

From Wikipedia: For the case that each xi is positive and bounded by the same constant, Pisinger found a linear time algorithm.

There is a different paper which seems to describe the same algorithm but it is a bit difficult to read for me so please - does anyone know how to translate the pseudo-code from page 4 (balsub) into working implementation?

Here are couple of pointers I collected so far:

www.diku.dk/~pisinger/95-6.ps (the paper) stackoverflow/a/9952759/1037407 www.diku.dk/hjemmesider/ansatte/pisinger/codes.html

PS: I don't really insist on precisely this algorithm so if you know of any other similarly performant algorithm please feel free to suggest it bellow.

Edit

This is a Python version of the code posted bellow by oldboy:

class view(object): def __init__(self, sequence, start): self.sequence, self.start = sequence, start def __getitem__(self, index): return self.sequence[index + self.start] def __setitem__(self, index, value): self.sequence[index + self.start] = value def balsub(w, c): '''A balanced algorithm for Subset-sum problem by David Pisinger w = weights, c = capacity of the knapsack''' n = len(w) assert n > 0 sum_w = 0 r = 0 for wj in w: assert wj > 0 sum_w += wj assert wj <= c r = max(r, wj) assert sum_w > c b = 0 w_bar = 0 while w_bar + w[b] <= c: w_bar += w[b] b += 1 s = [[0] * 2 * r for i in range(n - b + 1)] s_b_1 = view(s[0], r - 1) for mu in range(-r + 1, 1): s_b_1[mu] = -1 for mu in range(1, r + 1): s_b_1[mu] = 0 s_b_1[w_bar - c] = b for t in range(b, n): s_t_1 = view(s[t - b], r - 1) s_t = view(s[t - b + 1], r - 1) for mu in range(-r + 1, r + 1): s_t[mu] = s_t_1[mu] for mu in range(-r + 1, 1): mu_prime = mu + w[t] s_t[mu_prime] = max(s_t[mu_prime], s_t_1[mu]) for mu in range(w[t], 0, -1): for j in range(s_t[mu] - 1, s_t_1[mu] - 1, -1): mu_prime = mu - w[j] s_t[mu_prime] = max(s_t[mu_prime], j) solved = False z = 0 s_n_1 = view(s[n - b], r - 1) while z >= -r + 1: if s_n_1[z] >= 0: solved = True break z -= 1 if solved: print c + z print n x = [False] * n for j in range(0, b): x[j] = True for t in range(n - 1, b - 1, -1): s_t = view(s[t - b + 1], r - 1) s_t_1 = view(s[t - b], r - 1) while True: j = s_t[z] assert j >= 0 z_unprime = z + w[j] if z_unprime > r or j >= s_t[z_unprime]: break z = z_unprime x[j] = False z_unprime = z - w[t] if z_unprime >= -r + 1 and s_t_1[z_unprime] >= s_t[z]: z = z_unprime x[t] = True for j in range(n): print x[j], w[j]

解决方案

// Input: // c (capacity of the knapsack) // n (number of items) // w_1 (weight of item 1) // ... // w_n (weight of item n) // // Output: // z (optimal solution) // n // x_1 (indicator for item 1) // ... // x_n (indicator for item n) #include <algorithm> #include <cassert> #include <iostream> #include <vector> using namespace std; int main() { int c = 0; cin >> c; int n = 0; cin >> n; assert(n > 0); vector<int> w(n); int sum_w = 0; int r = 0; for (int j = 0; j < n; ++j) { cin >> w[j]; assert(w[j] > 0); sum_w += w[j]; assert(w[j] <= c); r = max(r, w[j]); } assert(sum_w > c); int b; int w_bar = 0; for (b = 0; w_bar + w[b] <= c; ++b) { w_bar += w[b]; } vector<vector<int> > s(n - b + 1, vector<int>(2 * r)); vector<int>::iterator s_b_1 = s[0].begin() + (r - 1); for (int mu = -r + 1; mu <= 0; ++mu) { s_b_1[mu] = -1; } for (int mu = 1; mu <= r; ++mu) { s_b_1[mu] = 0; } s_b_1[w_bar - c] = b; for (int t = b; t < n; ++t) { vector<int>::const_iterator s_t_1 = s[t - b].begin() + (r - 1); vector<int>::iterator s_t = s[t - b + 1].begin() + (r - 1); for (int mu = -r + 1; mu <= r; ++mu) { s_t[mu] = s_t_1[mu]; } for (int mu = -r + 1; mu <= 0; ++mu) { int mu_prime = mu + w[t]; s_t[mu_prime] = max(s_t[mu_prime], s_t_1[mu]); } for (int mu = w[t]; mu >= 1; --mu) { for (int j = s_t[mu] - 1; j >= s_t_1[mu]; --j) { int mu_prime = mu - w[j]; s_t[mu_prime] = max(s_t[mu_prime], j); } } } bool solved = false; int z; vector<int>::const_iterator s_n_1 = s[n - b].begin() + (r - 1); for (z = 0; z >= -r + 1; --z) { if (s_n_1[z] >= 0) { solved = true; break; } } if (solved) { cout << c + z << '\n' << n << '\n'; vector<bool> x(n, false); for (int j = 0; j < b; ++j) x[j] = true; for (int t = n - 1; t >= b; --t) { vector<int>::const_iterator s_t = s[t - b + 1].begin() + (r - 1); vector<int>::const_iterator s_t_1 = s[t - b].begin() + (r - 1); while (true) { int j = s_t[z]; assert(j >= 0); int z_unprime = z + w[j]; if (z_unprime > r || j >= s_t[z_unprime]) break; z = z_unprime; x[j] = false; } int z_unprime = z - w[t]; if (z_unprime >= -r + 1 && s_t_1[z_unprime] >= s_t[z]) { z = z_unprime; x[t] = true; } } for (int j = 0; j < n; ++j) { cout << x[j] << '\n'; } } }

更多推荐

通过Pisinger快速解决方案,以子集和算法

本文发布于:2023-11-29 11:28:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1646266.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:子集   算法   解决方案   快速   Pisinger

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!