子集和问题
Time Limit: 1000 ms Memory Limit: 65536 KiB
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>
#define MAX 10000
int data[MAX];
bool v[MAX];//默认都是false
int n, c;
bool traceback(int n) {
int p = 0, sum = 0;
while (p >= 0)
{
if (!v[p])//v[p]==false表示还未加入子集序列的元素
{
v[p] = true;
sum += data[p];
if (c == sum)
return true;
else if (c < sum)
{
v[p] = false;
sum -= data[p];
}
p++;
}
if (p >= n)
{
while (v[p - 1])//说明全部元素相加也小于c
{
p--;
v[p] = false;
if (p<1) return false;
}
while (!v[p - 1])//说明每个元素都大于c
{
p--;
if (p<1) return false;
}
sum -= data[p - 1];//说明有可能有这个子集,只是加上当前值不合适,回溯
v[p - 1] = false;
}
}
return false;
}
int main() {
scanf("%d %d", &n, &c);
for (int i = 0; i < n; i++)
scanf("%d", &data[i]);
if (traceback(n))
{
int first = 1;
for (int i = 0; i < n; i++)
if (v[i])
{
if (first)
first = 0;
else
printf(" ");
printf("%d", data[i]);
}
printf("\n");
}
else
printf("No Solution!\n");
return 0;
}