定义
一组进制的位格雷码,是一组有序的、无重复的、进制位数。这组数中一共有的次方个数。相邻的(因有序,所以有相邻的概念)两个数之间有且只有一位是不同的。这组数的第一个和最后一个数,也被视为相邻的数。
输入
一行和,分别表示格雷码位数和进制,其中
输出
任意一种格雷码编码方案,每个编码一行,相邻两行格雷码相差一位,第一行和最后一行也算相邻。
样例
输入
2 3
输出
00
01
02
12
10
11
21
22
20
生成算法
算法思想
设位进制格雷码的编码结果存储于字符串数组,构造位长度时字符串数组长度为
- 初始化,首先构造位进制格雷码的字符串数组,将依次插入数组,如位进制:
- 构造位编码,首先将位的编码结果复制成倍存于数组中,如:
- 对于位编码,长度为,将扩充后的数组按顺序分为组,如位进制:,第组循环右移位(计数从开始):
- 对于第组,在每个元素前插入数字,构成位进制格雷码的编码结果,如:
- 更新,重复第步直到
回溯实现
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string code[50001];//编码结果
int n,m;
int len;
void dfs(int k){
if(k==n+1){//搜索结束
return;
}
for(int i=len;i<m*len;i++){//复制为循环右移
code[i]=code[(i-i/len+len)%len];
}
for(int i=0;i<m*len;i++){//i组插入i前缀
code[i]=char('0'+(i/len%m))+code[i];
}
len*=m;//更新长度
dfs(k+1);
}
int main(){
cin>>n>>m;
len=1;//乘法不能用0作为初始值
dfs(1);//从1开始搜索
for(int i=0;i<len;i++){
cout<<code[i]<<endl;//输出结果
}
return 0;
}
循环实现
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string code[50001];//编码结果
int n,m,k,len;
int main(){
cin>>n>>m;
len=1;//乘法不能用0作为初始值
k=1;
while(k<=n){
for(int j=len;j<m*len;j++){//复制为循环右移
code[j]=code[(j-j/len+len)%len];
}
for(int i=0;i<m*len;i++){//i组插入i前缀
code[i]=char('0'+(i/len%m))+code[i];
}
len*=m;//更新长度
k++;
}
for(int i=0;i<len;i++){
cout<<code[i]<<endl;//输出结果
}
return 0;
}