問題基本描述:有一個揹包,能盛放的物品總重量爲S,設有N件物品,其重量分別爲w1,w2,...wn,希望從N件物品中選擇若干件物品,所選物品的重量之和恰能放入該揹包,即所選物品的重量之和等於S。
遞歸算法
#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();
}
非遞歸
#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();
}
堆棧不空的表達式應該是top>=1或者top>0,此處需要仔細體會stack[0]的內容和含義,否則我們很難正確構造堆棧不空的表達式;而未求得解表達式應該是k==0或者!k。