哈密顿回路-相异数字序列问题

来源:互联网 发布:微店和淘宝 编辑:程序博客网 时间:2024/04/27 18:51

要满足两个条件:

  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 65535struct 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;}


 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 班里选的班长成绩差怎么办 幼儿园班里孩子发生传染病怎么办 小仓鼠生了该怎么办 把老公生日忘了怎么办 老公说老婆脑子不好怎么办 和上司暧昧被同事发现怎么办 减肥不吃晚餐饿了怎么办 小孩晚饭吃多了怎么办 减肥晚上不吃饭饿了怎么办 两个人在一起性格不合怎么办 赌在你身上输了怎么办 苹果7lcould满了怎么办 e招贷不用了怎么办 牙活动了怎么办还疼 30岁掉了一颗牙怎么办? 在淘宝上交话费交错了怎么办 演出队在小区旁边扰民怎么办 雷雨天加了油怎么办 戴ok镜眼睛重影怎么办 乌龟背上长白色的花纹怎么办? 全自动洗衣机里面掉个硬币怎么办 跆拳道课上孩子乱动说话怎么办? 孩子不愿意上跆拳道课了怎么办 车座位里面倒了汤怎么办 腿被棍子打肿了怎么办 刚买的手机碎屏怎么办 被木棍么么打到头项怎么办 大王卡用到40g怎么办 王卡40g用完了怎么办 父亲把母亲打成重伤怎么办 狗狗脖子摔歪了怎么办 吃鸡游戏中重伤怎么办 吃鸡游戏摔伤了怎么办 现在没能力偿还网贷怎么办 上海找夜场工作被骗了怎么办? 买了烂尾的楼盘怎么办 孕七个月蛀牙疼怎么办 宝宝只吃一边奶怎么办 实房付了定金后悔了怎么办 开车时遇到意外事故时怎么办 没干过影楼门市怎么办