子集和问题(c语言实现)

5.1题目
算法实现题 5-1 子集和问题
★问题描述:子集和问题的一个实例为。其中,S={X1,X2,…Xn}是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得 Σx =c.
试设计一个解子集和问题的回溯法。
★算法设计:对于给定的正整数集合S={X1,X2,… Xn}和正整数c,计算S的一个集合S1,使得Σx=c。
★数据输入:由文件input.txt提供输入数据。文件第一行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中有n个正整数,表示集合S中的元素。
★结果输出:将子集和问题的解输出到文件output.txt。当问题无解时,输出“No Solution!”。
输入文件示例 输出文件示例
Input.txt output.txt
5 10 2 2 6
2 2 6 5 4

5.2分析
在我看来回溯算法就是找到问题的一个解,并不能找到问题的最优解,因此此类问题适合使用回溯算法,在回溯算法使用前应先画出一个大概的树状图,在使用回溯算法递归时定义局部静态变量以防止变量在递归时被刷新,或者定义全局变量也可,当余下数全选时加上当前数值大于常数c时即可继续加和,否则这条线路就没有了继续的必要,因为解必然不在此列。
5.3源代码

#include 
#include//回溯算法
int huisu(int i, int* p, int* q, int n);
int c = 10;
int main()
{
	FILE* fpr, * fpw;
	int i = 0, max, z, n ;
	int b[100], a[100];
	fopen_s(&fpr, "input.txt", "r");
	fopen_s(&fpw, "output.txt", "w");
	fscanf_s(fpr, "%d", &n);
	fscanf_s(fpr, "%d", &c);
	for (i = 0; i < n; i++)
		fscanf_s(fpr, "%d", a + i);
	z = huisu(i = 0, b, a, n);
	if(z!=0)
	for (i = 0; i < z; i++)
		fprintf(fpw, "%d ", *(b + i));
	else
		fprintf(fpw, "No Solution!");
	fclose(fpr);
	fclose(fpw);
	return 0;
}
int huisu(int i, int* p, int* q, int n)
{
	static int max = 0, r = c, z = 0;//局部静态变量存储max,保证递归时不丢失数据
	int  right;
	if ((max == c) && (i <= n))
		return z;
	if(i > n)
		return 0;
	if (max + r >= c)//走左侧
	{
		r -= q[i];
		right = q[i];
		max += right;
		p[z++] = right;
		huisu(i + 1, p, q, n);//递归
	}
	else
		huisu(i + 1, p, q, n);
}

5.4运行结果
子集和问题(c语言实现)_第1张图片
5.5总结
早上上课时刚刚讲过回溯算法就能在这里加以运用,巩固了所学知识,加深记忆并用以实践,其实回溯算法无非就是递归加判断。

你可能感兴趣的:(子集和问题(c语言实现))