zoukankan      html  css  js  c++  java
  • 【回溯法】求集合的子集

    给定一个集合比如{1,2,3},求该集合的所有子集。
    对于集合中的每一个元素,在某一子集中只有两种状态,要么在子集中,要么不在子集中。
    这里写图片描述
    因此对于一个含有n个元素的集合来说,对其中的某一个元素i,用xi来表示其在某一子集中的状态,xi=1表示在子集中,xi=0表示不在子集中,因此,解可以表示为:
    {x1,x2,x3,x4......xn};一共有2^n个向量。那么可以写代码如下.
    程序代码:

    #include<stdio.h>
    #define MAX 100
    void back(int i,int n);
    int a[MAX];//存储集合元素
    int count=0;//记录子集个数,其实没必要记录,因为count=2^n这是很显然的。
    int b[MAX]={0};//存储集合元素状态
    int k=1;//表示第k个元素,从1开始数
    int main()
    {
    	int i=0, n;
    	scanf("%d",&n);
    	for(i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	back(1,n);//从第一个元素开始,确定第一个元素的状态
    	printf("%d",count);
    	return 0;
    }
    void back(int i,int n)
    {
    	int j;
    	int sum =0;
    	if(i>n)//i>n表示所有元素的状态都已经确定,那么接下来打印出来
    	{
    		printf("{");
    		for(j=1;j<=n;j++)
    		{
    			if(b[j])	
    				printf("%d,",a[j]);
    				//sum +=a[j];求子集之和
    		}
    		//printf("%d",sum);
    		printf("}
    ");
    		count++;
    		return ;
    	}
    	{
    		b[i]=1;//取第i个元素
    		back(i+1,n);//处理下一个元素
    		b[i]=0;//不取第i个元素
    		back(i+1,n);//处理下一个元素
    	}
    	return ;	
    }
    
    

    运行结果:

    这里写图片描述

    更进一步,求符合某条件的子集,比如子集和为m。
    修改代码如下:

    #include<stdio.h>
    #define MAX 100
    void back(int i,int n,int m);
    int sum = 0;
    int a[MAX];//存储集合元素
    int count=0;//记录子集个数,其实没必要记录,因为count=2^n这是很显然的。
    int b[MAX]={0};//存储集合元素状态
    int k=1;//表示第k个元素,从1开始数
    int main()
    {
        int i=0, n;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        back(1,n,10);//从第一个元素开始,确定第一个元素的状态
        return 0;
    }
    void back(int i,int n,int m)
    {
        int j;
        //int sum =0;
        if(i>n)//i>n表示所有元素的状态都已经确定,但是其和不为m
        {
            return ;
        } 
        b[i]=1;//取第i个元素
    	sum +=a[i];
    	if(sum == m)
    	{
    		printf("{");
    		for(j=1;j<=i;j++)
    		{
    			if(b[j])
    				printf("%d,",a[j]);
    		}	
    		printf("}
    ");
    	}
    	else if(sum<m)
        {
    		 back(i+1,n,10);//处理下一个元素
        }
    	b[i]=0;
    	sum-=a[i];
        back(i+1,n,10);//处理下一个元素
        return ;    
    }
    
    

    程序运行结果:

    这里写图片描述

  • 相关阅读:
    洛谷1894 [USACO4.2]完美的牛栏The Perfect Stall
    洛谷2417 课程
    洛谷2860 [USACO06JAN]冗余路径Redundant Paths
    洛谷1983 车站分级
    BZOJ1178或洛谷3626 [APIO2009]会议中心
    BZOJ1179或洛谷3672 [APIO2009]抢掠计划
    CF Round #516 (Div. 2, by Moscow Team Olympiad)
    洛谷1262 间谍网络
    NOI导刊 2018河南郑州游记
    BZOJ1001或洛谷4001 [BJOI2006]狼抓兔子
  • 原文地址:https://www.cnblogs.com/zhengkang/p/5728350.html
Copyright © 2011-2022 走看看