问题描述:
设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;
}