要满足两个条件:
1.封闭的环
2.是一个连通图,且图中任意两点可达
经过图(有向图或无向图)中所有顶点一次且仅一次的通路称为哈密顿通路。
经过图中所有顶点一次且仅一次的回路称为哈密顿回路。
具有哈密顿回路的图称为哈密顿图,具有哈密顿通路但不具有哈密顿回路的图称为半哈密顿图。
平凡图是哈密顿图。
问题描述
给你一个整数m,找出这样一个长为2^m的0,1序列,使得依次取长为m的串时,得到的2^m个长为m的0,1串,它们表示了互不相同的十进制数。
输入:第一行是一个整数n,表示需考察n个整数(1<=n<=15),接着n行,每行有一个整数m(1<=m<=15)
样例:
2
2
3
m=2: 0011
m=3: 00010111
考察m=2的情形,长为2的序列00开始,每个序列后面接0或1,于是接0得000,前面两位00和后面两位的00相同,应排除本次接0的情况,应接1,变成001,后01与前00不同,应保留填上1.确定01后,对01后面接0或1,应该有010和011,都可行,取低2位10或11,类似接0或1.最后得出下面有向图。

#include <iostream>
using namespace std;
#define MAXN 65535
struct node
{
int left, right; // left,right分别记录当前节点通过添0,添1而得的序列
int visited; // 标记是否被访问到,-1表示未访问过,0表示左支,1表示右支
};
typedef node NODE;
NODE p[MAXN]; // 表示节点数组
long maxb, a[MAXN]; // a存放最优解
int m;
void init(int m) // 初始化构建一个有向图
{
long i, k;
maxb = (1<<m) - 1; // 记有向图的顶点最大顶点数-1
for (i = 0; i <= maxb; i++)
{
// 设定无左右儿子,无访问值
p[i].left = -1;
p[i].right = -1;
p[i].visited = -1;
k = i; // 考察当前十进制数是i的节点的左右儿子生成情况
k = (k << 1) & maxb; // 节点的二进制数尾添0,用位操作,取后m位
if (k != i)
{
p[i].left = k; // 去左支重复节点
}
k = k + 1; // 尝试右支
if (k != i)
{
p[i].right = k; // 去右支重复节点
}
}
}
// 判断数b与当前部分解a前k个是否有相同的
bool NotEqual(int k, int b)
{
bool flag = true;
int i;
for (i = 0; i <= k; i++)
{
if (a[i] == b)
{
flag = false;
break;
}
}
return flag;
}
// 求最优解a,采用迭代回溯算法
void Compt()
{
long i = 1, j;
bool flag = false;
a[0] = 0;
p[0].visited = 0;
while (true) // 搜索子树
{
while (i <= maxb && p[a[i-1]].left != -1 && p[a[i-1]].left != 0
&& NotEqual(i-1, p[a[i-1]].left))
{// 如左子树一直可行,沿左子树一直下去
a[i] = p[a[i-1]].left; //取左儿子值
p[a[i-1]].visited = 0; //设访问左儿子标志
i++;
flag = false; // 设定可能进入右子树标志
}
// 如果个数已经够了,直接输出结果
if (i > maxb)
{
for (j = 0; j <= maxb; j++)
{
cout << ((a[j]&(1<<(m-1)))>>(m-1)); // 按字符串输出
}
cout << endl;
return;
}
else // 如果个数未满足要求
{
// 若右子树可行进入右子树
if (p[a[i-1]].right != -1 && p[a[i-1]].right != 0 && NotEqual(i-1, p[a[i-1]].right))
{
a[i] = p[a[i-1]].right; //取右儿子值
p[a[i-1]].visited = 0; //设访问右儿子标志
i++;
flag = false; // 设定可能进入左子树标志
}
}
while (!flag) // 剪枝回溯
{
i--;
while (i > 0 && p[a[i-1]].visited == 1) // 沿右子树返回
{
a[i] = -1;
p[a[i-1]].visited = -1; // 取消访问标志
i--;
}
if (p[a[i-1]].right != -1 && p[a[i-1]].right != 0 && NotEqual(i-1, p[a[i-1]].right))
{
a[i] = p[a[i-1]].right; //取右儿子值
p[a[i-1]].visited = 1; //设访问右儿子标志
i++;
flag = true; // 设定可能进入左子树标志
}
}
}
}
int main()
{
int i, n;
cin >> n;
for (i = 0; i < n; i++)
{
cin >> m;
cout << "m=" << m << ":" << endl;
if (m <= 0)
{
cout << "Impossible!" << endl;
}
else
{
init(m);
Compt();
}
}
system("pause");
return 0;
}
文章探讨了哈密顿回路的概念,即在图论中经过所有顶点一次且仅一次的回路,并介绍了如何构建满足特定条件的0,1序列,确保形成互不相同的十进制数。通过实例分析了当m为2和3时的序列构造过程,揭示了这一问题的解决方案。"
122732002,8753399,VTK实战:如何根据颜色获取对比色,"['图形渲染', 'c++', '计算机图形学']
1821

被折叠的 条评论
为什么被折叠?



