以反射Gray碼的順序生成0,1的n元組的演算法-組合數學

kewlgrl發表於2016-10-13

以反射Gray碼的順序生成0,1的n元組的演算法

演算法步驟如下:

從n元組a[n-1]a[n-2]...a[0]=00...0開始;

a[n-1]a[n-2]...a[0]!=00...0時,執行下面操作:
①計算sum=a[n-1]+a[n-2]+...+a[0];

②如果sum是偶數,則改變a[0](從0變到1或是從1變到0);

③否則,確定這樣的j,使得a[j]=1且滿足j>i的所有i有a[i]=0(即這是從左邊開始第一個1),然後,改變a[j+1](從0變到1或是從1變到0)。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <bitset>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 10010
int a[maxn];
int n;

void Init()
{
    memset(a,0,sizeof(a));
}
bool Check()//檢查是否a[n-1]==1且其它全為0
{
    if(a[n-1]!=1) return false;
    for(int i=0; i<n-1; ++i)
        if(a[i]!=0) return false;
    return true;
}
int Sum()//陣列a所有元素之和
{
    int sum=0;
    for(int i=0; i<n; ++i)
        sum+=a[i];
    return sum;
}
void Change()//取反第一個1之前一位的數值
{
    for(int i=0; i<n; ++i)
        if(a[i]==1)
        {
            a[i+1]=!a[i+1];
            break;
        }
}
void Out()//輸出陣列a
{
    for(int i=n-1; i>=0; --i)
        cout<<a[i]<<" ";
    cout<<endl;
}
int main()
{
    cin>>n;
    Init();//初始化全部置零
    while(!Check())
    {
        Out();//輸出陣列a
        if(Sum()%2==0)//若所有元素之和為偶數
            a[0]=!a[0];//取反a[0]
        else if(Sum()%2==1)//若所有元素之和為奇數
            Change();//取反第一個1之前一位的數值
    }
    Out();//輸出陣列a
    return 0;
}


相關文章