8603子集和问题
8603 子集和问题
时间限制:1000MS 内存限制:1000K
提交次数:0 通过次数:0
题型: 编程题 语言: 无限制
Description
S 是一个整数集合,S={x1,x2,...,xn},c 是一个整数。这里集合元素xi (1
子集和问题就是:判断是否存在S 的一个子集S1,使得:
对S 集合子集树采用深度优先的顺序进行搜索,子集树从上到下每层标示着S 集合中每个从左到右元素“选”或者“不选”(左1右0)。
试着用回溯算法设计解子集和问题。
Input
第一行2个数:正整数n 和整数c 。n 表示S 集合的大小,c 是子集和的目标值,接下来一行中,有n 个整数,表示集合S 中的元素。
Output
将子集和问题的解输出,当无解时,输出"No Solution"(注意No Solution的大小写,空格,无标点)。
注意:依据S 集合元素从左到右依次来画子集树,因此子集树唯一。
若存在多种子集和问题的解时,只输出在这个唯一的子集树按深度优先方向遇到的第一个解,这样保证解的唯一性,利于评判。
如:5 10
2 2 6 3 3
这里,2+2+6=10,2+2+3+3=10,但只输出2 2 6
如:5 10
2 2 3 3 6
只输出2 2 3 3
又如:5 -30
2 -2 6 -30 -3
只输出2 -2 -30
Sample Input
5 10
2 2 6 5 4
Sample Output
2 2 6
Hint
解空间树是“子集树”。
回溯法搜索,由于是深度优先的找,找到就退出。
参考书上的“装载问题”和书上的“0-1背包问题”来写,因为都是搜索子集树。
但此题无法有很好的剪枝优化,因为所有整数有正有负,只有找到或找完整棵树才能退出。 Provider
zhengchan
Source Code #include
using namespace std;
int n,c,cw,flag=0;
int x[60],w[60];
void backTrack(int i);
int main()
{
int i;
cin>>n>>c;
cw=0;
for(i=0;i
{
cin>>w[i];
x[i]=0;
}
backTrack(0);
if(flag)
{
for(i=0;i
if (x[i]==1)
cout
else
cout
cout
return 0;
}
void backTrack(int i)
{
if(i>n-1)
{
if(cw==c)
{
flag=1; return;
} } return; } if(cw+w[i]!=c) { x[i]=1; cw+=w[i]; backTrack(i+1); if(flag) return; x[i]=0; cw-=w[i]; backTrack(i+1); if(flag) return; } if(cw+w[i]==c) { flag=1; x[i]=1; return; }