子集生成

子集生成

1.该数二进制的所有组合的集合

# include <bits/stdc++.h>
using namespace std;

int a[20],v[1<<16],dp[1<<16];
int dfs(int s,int now)
{
   if(dp[s]) return dp[s];
   int ans=0;
   for(int i=s;i>1;i=(i-1)&s){
       if(v[i]){
           ans=max(dfs(s-i,now+v[i])+a[now+v[i]],ans);
      }
  }
   return dp[s]=ans;
}
int main()
{
   int ans=0;
   int N,M; scanf("%d%d",&N,&M);
   for(int i=1;i<=N;++i){
       scanf("%d",&a[i]);
       ans+=a[i];
  }
   sort(a+1,a+N+1,greater<int>());
   for(int i=1;i<=M;++i){
       int s=0;
       int x,y; scanf("%d",&x);
       for(int j=1;j<=x;++j){
           scanf("%d",&y);
           s|=(1<<y);
      }
       v[s]=x;
  }
   ans-=dfs((1<<(N+1))-1,0);
   printf("%d\n",ans);
   return 0;
}

2.包含n各元素的集合的子集

# include <bits/stdc++.h>
using namespace std;

const int MAXN=1e5+100;
int n,A[16],B[16];
//增量构造法
int ans=0;
void dfs1(int cur)
{
   for(int i=0;i<cur;++i){//打印当前集合
       printf("%d ",A[i]);
  }
   ans++;
   printf("\n");
   int s=cur?A[cur-1]+1:0;//确定当前元素的最小可能
   for(int i=s;i<n;++i){
       A[cur]=i;
       dfs1(cur+1);
  }
}
//位向量法
void dfs2(int cur)
{
   if(cur==n){
       for(int i=0;i<cur;++i){//打印集合
           if(B[i]) printf("%d ",i);
      }
       ans++;
       printf("\n");
       return ;
  }
   B[cur]=1; dfs2(cur+1);
   B[cur]=0; dfs2(cur+1);
}
//二进制法
void dfs3(int cur)
{
   for(int i=0;i<n;++i){
       if(cur&(1<<i)) printf("%d ",i);
  }
   ans++;
   printf("\n");
}
int main()
{
   scanf("%d",&n);
   //dfs1(0);
   //dfs2(0);
   for(int i=0;i<(1<<n);++i) dfs3(i);
   //cout<<"!!!!"<<ans<<endl;
   return 0;
}



posted @ 2022-02-26 23:06  fengzlj  阅读(95)  评论(0)    收藏  举报