问题基本描述:有一个背包,能盛放的物品总重量为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(!k && 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。