“背包问题”的算法

来源:互联网 发布:杨辉三角c语言程序编写 编辑:程序博客网 时间:2024/04/27 17:32

问题基本描述:有一个背包,能盛放的物品总重量为S,设有N件物品,其重量分别为w1,w2,...wn,希望从N件物品中选择若干件物品,所选物品的重量之和恰能放入该背包,即所选物品的重量之和等于S。

递归算法

 

#include <stdio.h>
#define N 7
#define S 15
int w[N+1= {0,1,2,3,4,5,6,7};

int knap(int s, int n)
{
    
if(s == 0)
        
return 1;
    
if(s < 0 || s >0 && n < 1)
        
return 0;
    
if(knap(s - w[n], n-1))
    
{
        printf(
"%4d ", w[n]);
        
return 1;
    }

    
return knap(s, n-1);
}

void main()
{
    
if(knap(S, N))
        printf(
"OK! ");
    
else
        printf(
"NO! ");
    getchar();
}

 非递归

 

#include <stdio.h>
#define N 7
#define S 15
typedef 
struct
{
    
int s;
    
int n;
    
int job;
}
KNAPTP;
int w[N+1= {0,1,4,3,4,5,2,7};

int knap(int s, int n)
{
    KNAPTP stack[
100], x;
    
int top, k, rep;
    x.s 
= s; x.n = n;
    x.job 
= 0;
    top 
= 1; stack[top] = x;
    k 
= 0;
    
while(top > 0 && k == 0)
    
{
        x 
= stack[top];
        rep 
= 1;
        
while(!&& rep)
        
{
            
if(x.s == 0)
                k 
= 1//caught an answer
            else if(x.s < 0 || x.n <= 0)
                rep 
= 0;
            
else
            
{
                x.s 
= x.s - w[x.n--];
                x.job 
= 1;
                stack[
++top] = x;
            }

        }

        
if(!k) //watch rep = 0;
        {
            rep 
=1;
            
while(top >= 1&& rep)
            
{
                x 
= stack[top--];
                
if(x.job == 1)
                
{
                    x.s 
+= w[x.n + 1];
                    x.job 
= 2//change it as discard one
                    stack[++top] = x;
                    rep 
= 0;
                }

            }

        }

    }

    
if(k) // found an answer
    {
        
while(top >= 1)
        
{
            x 
= stack[top--];
            
if(x.job == 1)
                printf(
"%d ", w[x.n + 1]);
        }

    }

    
return k;
}

void main()
{
    
if(knap(S, N))
        printf(
"OK! ");
    
else
        printf(
"NO ");
    getchar();
}
求解部分的循环执行条件是堆栈不空且未找到解,因为当堆栈空的时候表示程序已经穷尽了所有的可能,这是使用堆栈的程序的一般特征。(利用堆栈对不在结果集中的数据进行回溯,堆栈中o的位置存放S和N,注意top的初始值是1并不是栈底),考虑数据int w[N+1] = {0,1,1,1,1,1,1,1};
堆栈不空的表达式应该是top>=1或者top>0,此处需要仔细体会stack[0]的内容和含义,否则我们很难正确构造堆栈不空的表达式;而未求得解表达式应该是k==0或者!k。
原创粉丝点击