背包 - 节省时间和内存 [英] Knapsack - save time and memory

查看:139
本文介绍了背包 - 节省时间和内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据维基百科和其他来源我有经历了,你需要矩阵 M [N] [W] ; N - 项目数和是W - 总背包的容量。该矩阵得到真正的大,有时太大,处理它的C程序。我知道,动态编程是基于节省时间的记忆,但仍然是有你在那里可以节省时间和内存的任何解决方案?

伪$ C $下背包问题:

  //输入:
//值(存储在数组v)的
//重量(存储在数组w)
//不同项目数(n)的
//背包容量(W)
对于j从0到w请勿
  米[0,j]中:= 0
结束了
对于i从1到n做
  对于j从0到w请勿
    当w [1]  - ; = j的再
      米[I,J]:=最大值(米[I-1,j]的,米[I-1,J-瓦特[I] + V [I])
    其他
      米[I,J]:=米[I-1,j]的
    如果结束
  结束了
结束了
 

可以说,是W = 123456789和n = 100。在这种情况下,我们得到了真正的大矩阵m [100] [123456789]。我在想如何实现这一点,但最好的,我有我的脑海里只是挽救哪些项目是有一个位(0/1)中选择。这可能吗?或者有没有其他的方法来这个问题?

  INT32  - > 32 * 123456789 * 100位
one_bit  - > 1 * 123456789 * 100位
 

我希望这不是愚蠢的问题,感谢你的努力。

修改 - 工作C code:

 长INT I,J;
    长整型* M [2];
    M [0] =(长整型*)malloc的(的sizeof(长整型)*(W + 1));
    米[1] =(长整型*)malloc的(的sizeof(长整型)*(W + 1));
    对于(i = 0; I< = W;我++){
        米[0] [I] = 0;
    }

    INT读= 0;
    INT写= 1;
    INT TMP;

    长整型百分比=(W + 1)*(N)/ 100;
    长整型计数器= 0;

    对于(i = 1; I< = N;我++){
        为(J = 0; J< = W; J ++){
            如果(瓦特[I-1] = j)条{
                M [写入] [J] = MAX(M [阅读] [J],(V [I-1)+ M [阅读] [J-(W [I-1])]);
            }其他{
                M [写入] [J] = M [阅读] [J]。
            }
            反++;
            如果(计数器==百分比){
                输出(。); //打印点(。),每百分数
                fflush(标准输出);
                计数器= 0;
            }
        }
        TMP =读取;
        读=写;
        写= TMP;
    }

    的printf(\ N%LD \ N,M [阅读] [W]);

    免费(M [0]);
    免费(M [1]);
 

解决方案

背包问题可以通过使用 0(W)的空间来解决。
在迭代的每一步,你只需要2行 - 阵列的当前状态 M [] M [+ 1]

 电流= 1
INT米[2] [W]
设置为NONE M#这意味着我们无法处理这种情况下的所有元素
M [0] [0] = 0#这是我们的起点,初始为空背包

因为我在[1..1]做
    接下来= 3  - 电流; ///只使用1或2基于当前指数
    对于j在[0 ... W]做
       M [下一页] [J] = M [当前] [J]。
    对于j在[W [I] ... W]做
       如果m [当前] [J  -  W [我]不无则#过程只到达位置
           M [下一页] [J] = MAX(M [下一页] [J],M [电流] [J  -  W [I]] + V [I]);
    电流=下一个; ///交换当前状态和产生的1
 


此外,也可以只使用1阵列。这里是伪code

 因为我在[1..1]做
    对于j在[W [I] ... W]做
       M [J] = MAX(M [J],男[J  -  W [I]] + V [I]);
 

According to Wikipedia and other sources I had went through, you need matrix m[n][W]; n - number of items and W - total capacity of knapsack. This matrix get really big, sometimes too big to handle it in C program. I know that dynamic programming is based on saving time for memory but still, is there any solution where can you save time and memory?

Pseudo-code for Knapsack problem:

// Input:
// Values (stored in array v)
// Weights (stored in array w)
// Number of distinct items (n)
// Knapsack capacity (W)
for j from 0 to W do
  m[0, j] := 0
end for 
for i from 1 to n do
  for j from 0 to W do
    if w[i] <= j then
      m[i, j] := max(m[i-1, j], m[i-1, j-w[i]] + v[i])
    else
      m[i, j] := m[i-1, j]
    end if
  end for
end for

Lets say, that W = 123456789 and n = 100. In this case we get really big matrix m[100][123456789]. I was thinking how to implement this, but best I have in my mind is just to save which items was selected with one bit (0/1). Is this possible? Or is there any other approach for this problem?

int32 -> 32 * 123456789 * 100 bits
one_bit -> 1 * 123456789 * 100 bits

I hope this is not stupid question and thanks for your effort.

EDIT - working C code:

    long int i, j;
    long int *m[2];
    m[0] = (long int *) malloc(sizeof(long int)*(W+1));
    m[1] = (long int *) malloc(sizeof(long int)*(W+1));
    for(i = 0; i <= W; i++){
        m[0][i] = 0;
    }

    int read = 0;
    int write = 1;
    int tmp;

    long int percent = (W+1)*(n)/100;
    long int counter = 0;

    for(i = 1; i <= n; i++){
        for(j = 0; j <= W; j++){
            if(w[i-1] <= j){
                m[write][j] = max(m[read][j],(v[i-1]) + m[read][j-(w[i-1])]);
            }else{
                m[write][j] = m[read][j];
            }
            counter++;
            if(counter == percent){
                printf(".");    //printing dot (.) for each percent
                fflush(stdout);
                counter = 0;
            }
        }
        tmp = read;
        read = write;
        write = tmp;
    }

    printf("\n%ld\n", m[read][W]);

    free(m[0]);
    free(m[1]);

解决方案

Knapsack problem can be solved using O(W) space.
At each step of the iteration you need only 2 rows - current state of the array m[i] and m[i + 1].

current = 1
int m[2][W]
set NONE for all elements of m # that means we are not able to process this state
m[0][0] = 0 # this is our start point, initially empty knapsack

FOR i in [1..n] do
    next = 3 - current; /// just use 1 or 2 based on the current index
    for j in [0...W] do
       m[next][j] = m[current][j]
    FOR j in [w[i]..W] do
       if m[current][j - w[i]] is not NONE then  # process only reachable positions
           m[next][j] = max(m[next][j], m[current][j - w[i]] + v[i]);
    current = next; /// swap current state and the produced one


Also it is possible to use only 1 array. Here is the pseudocode

FOR i in [1..n] do
    FOR j in [w[i]..W] do
       m[j] = max(m[j], m[j - w[i]] + v[i]);

这篇关于背包 - 节省时间和内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆