题目
给定一个整数数组nums和一个正整数k,找出是否有可能把这个数组分成k个非空子集,其总和都相等。
实例1:
输入:nums=[4,3,2,3,5,2,1],k=4
输出:True
说明:有可能将其分成4个子集(5),(1,4),(2,3),(2,3)等于总和
c语言代码
#include <stdio.h>
int nums[101];//存放所有的数
int sum=0;//存放所有的数的和
int average=0;//每个集合内所有数的和
int n;//总共多少个数
int k;//k个集合
int max=0; //所有的数里面的最大值
bool visited[101];//标记该数是否被选择
bool dfs(int setNums,int curSum,int start)//setNums剩余几个未分配,curSum目前分配的已有的和,start从哪里开始往后找
{
if(setNums==0) //当前所有的集合都分配到了
return true;
if(curSum==average)//当前该集合分到了average,该对下一个集合进行分配了
return dfs(setNums-1,0,0);
for(int i=0;i<n;i++)//对于一个集合可直接从i往后分配,新的则从0开始
{
if(!visited[i]&&curSum+nums[i]<=average)//该数未被选择,并且能够放进当前集合
{
visited[i]=true; //可分配标记
if(dfs(setNums,curSum+nums[i],i+1)) //加入该数后若分配成功返回true
//当为该集合找下一个数时直接可以从i+1往后找节省时间
return true;
visited[i]=false;//回溯
}
}
return false;//所有的数都遍历了,未分配成功返回false
}
int main()
{
scanf("%d",&n);//输入数组内数的个数
for(int i=0;i<n;i++)//输入数,求和,求最大值
{
scanf("%d",&nums[i]);
sum+=nums[i];
if(nums[i]>max)
max=nums[i];
}
scanf("%d",&k);//输入k
average=sum/k;//求平均值
if(sum%k!=0||max>average) //所有的和不能够分成k个相等的集合,集合里面有最大值大于平均值
{printf("flase");
return 0;
}
if(dfs(k,0,0))
{
printf("true");
return 0;
}
printf("false");
return 0;
}