首页 > 其他 > 详细

求子集的两种方法(模拟法,dfs法)

时间:2021-08-08 15:54:55      阅读:11      评论:0      收藏:0      [点我收藏+]

方法1:模拟法

我们以(1,2,3)这个集合为例手动模拟一遍

该集合的子集分别为:

一:空集

二:1

三:12

四:123

五:13

六:2

七:23

八:3

我们分析一下这个过程,选择第一个数字,选择其之后的数字依次加入,到了边界后退回,直到遍历完第一个数字的所有子集,然后对第二个数字重复同样的操作,直到把集合内所有的数字遍历完

不难发现,这个过程是一直向后的,被遍历完所有子集的数字不会再次出现,这也保证了不会重复计算,接下来我们就可以开始实现了

我们设一个数组a[]用来存放原集合,一个数组b[]用来存放子集,变量now表示现在正在原集合的第几个数字上,变量num表示现在正在子集的第几位上

void solve (int now,int num)

{

 

if(now>n)return;  //边界条件

for(int i=now;i<=n;i++)     //从原集合中依次选择元素加入子集,从now开始意味着只能选择当前元素及以后的元素加入

{

b[num]=a[i];   //选择当前位置的子集的元素

 

for(int j=1;j<=num;j++)

    cout<<b[j]<<" ";

cout<<endl;        //打印

 

solve(i+1,num+1);   //num+1意味着开始选择子集的下一位元素,i+1意味着接下来将会从当前元素之后的元素里选择

}

 

}

 

方法2:dfs法

不难发现,对于原集合中的每一个元素,都只存在两种情况:子集中有它,子集中没有它,等价一下就变成了:选择把它加入子集,选择不把它加入子集,接下来就可以开始实现了

我们设一个bool数组vis[]用来判断每个元素是否被选择,vis[]=1代表被选择,now 的定义同上

void dfs(int now)

{

if(now>n)
{

for(int i=1;i<=n;i++)

    if(vis[i])   //如果这个元素被选择了就打印

      cout<<b[i];

cout<<endl;

return;

}        //边界+打印

vis[i]=1;//表示选择这个元素

dfs(now+1);

vis[i]=0;//表示不选择这个元素

dfs(now+1);

}

求子集的两种方法(模拟法,dfs法)

原文:https://www.cnblogs.com/pcpcppc/p/15114426.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!