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