子集和问题
Problem Description
子集和问题的一个实例为〈S,t〉。其中,S={ x1 , x2 ,…,xn }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得:。
试设计一个解子集和问题的回溯法。
对于给定的正整数的集合S={ x1 , x2 ,…,xn }和正整数c,计算S 的一个子集S1,使得:。
Input
输入数据的第1 行有2 个正整数n 和c(n≤10000,c≤10000000),n 表示S 的大小,c是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。
Output
将子集和问题的解输出。当问题无解时,输出“No Solution!”。
Sample Input
5 10 2 2 6 5 4
Sample Output
2 2 6
Hint
Source
回溯法应用实例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int a[10000];
int v[10000];
int ans[10000];
int n, c, flag;
void DFS(int x)
{
int i;
if(flag == 1)
return; //如果找到了就会停止寻找
for(i = 0;i < n;i++)
{
if(v[i] == 0&&c-a[i] >= 0) //寻找没被标记,并且符合要求的数
{
if(flag == 1)
return; //如果找到了就会停止寻找
c -= a[i]; //更新c的值
v[i] = 1; //找到了就会置位
ans[x] = a[i]; //将找到的存入到寄存数组中
if(c == 0) //最后全部找到了,输出
{
if(flag == 0) //输出时挑选没标记的
{
for(i = 0;i <= x;i++)
{
printf("%d ",ans[i]);
}
printf("\n");
}
flag = 1; //代表找到了
return ;
}
else
{
DFS(x+1); //如果当前的数不满足就寻找下一个,x+1
if(flag == 1)
return;
v[i] = 0; //回溯
c += a[i];
}
}
}
}
int main()
{
int i, sum = 0;
scanf("%d %d",&n,&c);
for(i = 0;i < n;i++)
{
scanf("%d",&a[i]);
sum += a[i];
}
if(sum < c)
printf("No Solution!\n");
else
{
memset(v,0,sizeof(v)); //标记数组置位
memset(ans,0,sizeof(ans));// 寄存数组置位
flag = 0; //初始化标记变量
DFS(0); //从第一个数开始DFS
if(flag == 0) //如果没有找到
{
printf("No Solution!\n");
}
}
return 0;
}