1. 程式人生 > >【算法競賽入門經典】7.3子集生成【增量構造法】【位向量法】【二進制法】

【算法競賽入門經典】7.3子集生成【增量構造法】【位向量法】【二進制法】

subset 3.2 code == tdi style 構造 算法 nbsp

7.3.1增量構造法

思路:一次選出一個元素放到集合中。自己對於遞歸的理解還是不夠,這裏雖然沒有明確給出遞歸停止條件,但是如果無法繼續添加元素,就不會再繼續遞歸,然後就是我頭疼的回溯啦。

#include<stdio.h>

int num[4],n;

void A(int n,int *a,int ans)
{
    for(int i = 0; i < ans; i ++)//打印當前元素 
        printf("%d ",a[i]);
    printf("\n");
    int s = ans?a[ans-1]+1:0;//確定當前元素的最小可能值 
for(int i = s; i < n; i ++) { a[ans] = i; A(n,a,ans+1);//遞歸構造子集 } return; } int main() { n = 3; A(n,num,0); return 0; }

7.3.2位向量法

思路:構造一個位向量a[i],如果a[i]=1,當且僅當i在集合子集a中。

#include<stdio.h>
int num[4],n;

void print_subset(int n,int
*a,int ans) { if(ans == n) { for(int i = 0; i < ans; i ++)//打印當前集合 if(a[i]) printf("%d ",i); printf("\n"); return; } a[ans] = 1;//選擇第cur個元素 print_subset(n,a,ans+1); a[ans] = 0;//不選第cur個元素 print_subset(n,a,ans+1
); return; } int main() { n = 3; print_subset(n,num,0); return 0; }

7.3.3二進制法

#include<stdio.h>
int n = 3;
void print_subset(int n,int ans)
{
    for(int i = 0; i < n; i ++)//打印{0,1,2,3..n-1}的子集ans 
        if(ans&(1<<i))
            printf("%d ",i);
    printf("\n");
    return;
}

int main()
{
    for(int i = 0; i < (1<<n); i ++)//枚舉各子集對應的編碼 
        print_subset(n,i);
    return 0;
}

【算法競賽入門經典】7.3子集生成【增量構造法】【位向量法】【二進制法】