无和集问题(回溯)

问题描述: 
设S 是正整数集合。S 是一个无和集,当且仅当x,y属于S, 蕴含 x+y不属于S。 
对于任意正整数k ,如果可将 {1,2,…,k}划分为n个无和子集S1,S2,…,Sn,
称正整k 是n可分的。记 F(n)=max{ k | k 是n可分的}。 
试设计一个算法,对任意给定的n,计算 F (n ) 的值。 
编程任务: 
对任意给定的n,编程计算 F (n ) 的值。

数据输入: 
由文件input.txt给出输入数据。第一行有 1 个正整数n。 
结果输出: 
将计算出的 F (n ) 的值以及{1,2,…F(n)}的一个 n 划分输出到文件 output.txt。文件的
第一行是  F(n)的值。接下来的n行,每行是一个无和子集 Si。

输入文件示例          输出文件示例 
input.txt              output.txt 
2                          8 
                            1 2 4 8 

                            3 5 6 7

算法思想:从1开始回溯,建立两个两个二维数组,一个存放中间值,一个存放最终的结果。

dfs(1)  a[0][1]  a[0][0]++  t+1

dfs(2)  a[0][2]  a[0][0]++  t+1

dfs(3)  a[0][3]不满足,a[1][1]  a[1][0]++  t+1

dfs(4)  a[0][3]或者a[1][2]都满足 回溯尝试,找到一个k最大的情况

……

dfs(9)  a[0][5]和a[1][5]都不满足,退出,k=9-1=8.  

#include<stdio.h>

#define N 100

int F[N][N],answer[N][N];

int n,maxValue; 

int judge(int t,int k){
	int i,j;
	for(i=1;i<=F[k][0];i++){
		for(j=i+1;j<=F[k][0];j++){
			if(F[k][i]+F[k][j]==t)
			   return 0;
		}
	}
	return 1;
	
}

void dfs(int t){
	int i,j;
	if(t>maxValue){
		for(i=0;i<n;i++){
			for(j=0;j<=F[i][0];j++){  
				answer[i][j] = F[i][j];
			}
		}
		maxValue = t;
	}
	
	for(i=0;i<n;i++){
		F[i][F[i][0]+1]=t;
		if(judge(t,i)){
			F[i][0]+=1;
			dfs(t+1);
			F[i][0]-=1;
		}
	} 
}

void output(){
	int i,j;
	printf("%d\n",maxValue-1);
	for(i=0;i<n;i++){
		for(j=1;j<=answer[i][0];j++){
			printf("%d\t",answer[i][j]);
		}
		printf("\n");
	} 
}

int main(){
	
	scanf("%d",&n);
	maxValue = 0;
	dfs(1);
	output();
	return 0;
}

    原文作者:回溯法
    原文地址: https://blog.csdn.net/jhno99/article/details/78646405
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞