回 帖 发 新 帖 刷新版面

主题:[讨论]编了一个背包

这个程序是从小到大输出所给的几个数的所有组合。编01背包问题时我遇到了个困难,就是一个包只能用一次,但是如何排除重复的情况呢?比如求2,3,7的组合,有2,3,4,5,6,7,8....错了吧,4,6,8哪来的?因为我没有考虑到4=2+2,6=3+3,8=4+4的重复的现象,如果不增加一个很麻烦的步骤判断之前是否曾经出现过当前要加的数,实在想不到有什么简洁的方法了,这就是check()这堆垃圾诞生的原因。不知道有没有简单的方法啊?

#include <iostream>

using namespace std;

int comnum[100];

int check (int hash[], int i, int j)
{
    int x = j, f = i - j, ci = 0;

    if (hash[f] == 0)
        return 0;
    comnum[ci++] = x;

    int f0 = f;
    // search x
    while (hash[f] != -1) {
        int a = hash[f];
        int b = f - a;
        if (x == b)
            return 0;
        comnum[ci++] = b;
        f = a;
    }
    if (x == f)
        return 0;
    comnum[ci++] = f;
    // show
    cout << i << '=';
    for (int k = 0; k < ci - 1; ++k)
        cout << comnum[k] << '+';
    cout << comnum[ci - 1] << '\n';

    return f0;
}

int knap (int org[], int n, int hash[])
{
    int sum = 0;

    for (int i = 0; i < n; ++i)
        hash[org[i]] = -1;
    for (int i = 0; i < n; ++i)
        sum += org[i];
    for (int i = 0; i <= sum; ++i)
        if (hash[i] == 0)
            for (int j = 0; org[j] < i && j < n; ++j) {
                int f = check (hash, i, org[j]);
                if (f) {
                    hash[i] = f;
                    break;
                }
            }

    return sum;
}

int main ()
{
    int org[5] = {3,5,7,11,13};
    int hash[100] = {0};

    int sum = knap (org, 5, hash);

system ("pause");
    return 0;
}

回复列表 (共6个回复)

沙发

楼主的意思不是很明白。。。

板凳

如果背包里边东西不太多的话,还是可以做的~~~先来一个数,然后按照它的二进制表示的每一位来安排背包,然后加1,循环往复直至那个数等于2^n,这里n是背包里边的东西数~~~这就相当于遍历了所有可能的组合~~~

3 楼

整数0/1背包可以动态规划,复杂度O(BN),原来C语言实习的时候编过,如果我没有记错。

4 楼

你的程序里怎么没有背包大小?用二进制和直接搜索没什么区别,复杂度是一样的。

5 楼

对啊,2楼那是穷举.. 
实际上sum就是背包大小,饿默认就是所有物品的和,这样可以实验所有情况- -. 运行结果就是: 
8=3+5
10=3+7
12=5+7
14=3+11
15=3+5+7
16=3+13
18=5+13
19=5+3+11
20=7+13
21=3+5+13
23=3+7+13
24=11+13
25=5+7+13
26=7+5+3+11
27=3+11+13
28=3+5+7+13
29=5+11+13
31=7+11+13
32=3+5+11+13
34=3+7+11+13
36=5+7+11+13
39=3+5+7+11+13

check所用的方法比较复杂,我自己都说不清,等饿先清醒一下.

6 楼

int make(int num,int total, int ever[])
{
    if(total==0)
    return 1;
else if(total<0||(total>0&&num<1))
    return 0;
    else
    {
    if(make(num-1,total-ever[num-1],ever)==1)
        {
            printf("\tNO.:\n\t%d\\t重量:\n\t%d\n",num,ever[num-1]);
            printf("\n");
            printf("\n");
    return 1;
    }
    else
    return make(num-1,total,ever);
    }
}
    
main()
{int a,i,b,c;
int mg[1000];
printf("请输入一共有多少件物品:\n");
scanf("%d",&a);
printf("请输入每一件物品的重量:\n");
for(i=0;i<a;i++)
{printf("NO.%d\n",i+1);
scanf("%d",&mg[i]);
}
printf("请输入你的包可以放物品的重量:\n");
scanf("%d",&b);
printf("\n");
printf("\n");
c=make(a,b,mg);
if(c==0)
    printf("\n\tNO ANSWER!\n");
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册