1子集和问题 (50 分)
设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,
使S1中的元素之和为c。试设计一个解子集和问题的回溯法。
输入格式:
输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,
表示集合S中的元素。 是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。
输出格式:
将子集和问题的解输出。当问题无解时,输出“No Solution!”。
输入样例:
在这里给出一组输入。例如:
5 10
2 2 6 5 4
输出样例:
在这里给出相应的输出。例如:
2 2 6
//注意:这个题目只要输出一个解就可以了、
# include<iostream>
using namespace std;
int a[10000], n, t, b[10000] = {0}, z = 0;
int c[10000];
void print(int k)
{
int i;
z++;
for(i = 1; i <= k; i++)
{
cout<<c[i]<<" ";
}
cout<<endl;
}
int ff()
{
int i = 1, sum = 0, j = 1;
while(i > 0)
{
if(b[i] == 0)
{
b[i] = 1;
sum += a[i];
c[j] = a[i];
j++;
i++;
if(sum == t) return j;
if(sum > t)
{
sum -= a[i-1];
b[i-1] = 0;
j--;
}
if(i > n)
{
i = n - 1;
if(b[n] == 1)
{
sum -= a[n];
b[n] = 0;
j--;
}
while(b[i] == 0)
{
i--;
if(i < 0) return 0;
}
j--;
sum -= a[i];
b[i] = 0;
i++;
}
}
}
return 0;
}
int main()
{
int i, j, tol = 0;
cin>>n>>t;
for(i = 1; i <= n; i++)
{
cin>>a[i];
tol += a[i];
}
if(tol >= t)
{
j = ff();
if(j)
{
print(j-1);
}
else cout<<"No Solution!";
}
else cout<<"No Solution!";
return 0;
}
2 前t个组合结果 (25 分)
组合结果
找出从自然数1、2、… 、n(0<n<=30)中任取r(0<r<=n)个数的组合,输出其中前t个组合结果。
输入格式:
在一行中输入n、r、t(1<=t<=C(n,r))。
输出格式:
按特定顺序输出前t个组合结果,每一个组合结果占一行,含第一个整数在内的每一个整数前面都用一个空格,
最后一个整数后面没有空格。 特定顺序:每一个组合结果中的值从大到小排列,组合之间按逆字典序排列。
输入样例: