麻将回溯算法(无癞子)

  1 #include <stdio.h>
  2 #include <iostream>
  3 #include <sstream>
  4 #include <cstring>
  5 #include <vector>
  6
  7 using namespace std;
  8 typedef unsigned char byte;
  9 #define Arrlen(arr) sizeof(arr)/sizeof(arr[0])
 10
 11 byte arr[11] = {0x01,0x01,0x01,0x02,0x02,0x03,0x03,0x03,0x02,0x04,0x04};
 12 byte arrIndex[5] = {0};
 13 vector<byte> tempArr;
 14 vector<byte> allGroup;
 15
 16 byte SwitchToCardIndex(byte cbCardData)
 17 {
 18     return cbCardData - 1;
 19 }
 20
 21 byte SwitchToCardData(byte cbCardIndex)
 22 {
 23     return cbCardIndex + 1;
 24 }
 25
 26 void GetWeaveItem(byte dep)
 27 {
 28
 29     //每一种全部组合的区别最终在于将牌的不同,即以将牌的递归遍历为最终的根,可以保证结果的不重复
 30     //遍历每个Index,如果Index兑换成组合后,能否使dep=3,不能则+3还原,去兑换其他的组合
 31     //不区分组成组合的顺序,而是以所有的Index为组合的root节点,枚举所有的组合,并+3还原知道为true
 32     //为true时输出该手牌就OK,注意回溯时的出栈,即缓冲区的回溯
 33
 34     if (dep == 3 && tempArr.size() == Arrlen(arr))
 35     {
 36         cout << "可以和牌" <<endl;
 37
 38         for(auto itr = tempArr.begin();itr < tempArr.end();itr++)
 39         {
 40             if (itr == tempArr.begin())
 41             {
 42                 cout << (short)*itr;
 43             }
 44             else if (itr == tempArr.begin() + 1)
 45                 cout << (short)*itr << ",";
 46             else
 47                 cout << (short)*itr << " ";
 48             /*allGroup.push_back((short)*itr);*/
 49         }
 50
 51         cout << endl << endl;
 52     }
 53
 54     for (int i = 0; i < Arrlen(arrIndex); i++)
 55     {
 56         if (arrIndex[i] >= 3)
 57         {
 58             arrIndex[i] -= 3;
 59             tempArr.push_back(SwitchToCardData(i));
 60             tempArr.push_back(SwitchToCardData(i));
 61             tempArr.push_back(SwitchToCardData(i));
 62
 63             GetWeaveItem(dep+1);
 64
 65             arrIndex[i] += 3;
 66             tempArr.pop_back();
 67             tempArr.pop_back();
 68             tempArr.pop_back();
 69
 70         }
 71     }
 72
 73     //最后两张不再需要判断
 74     for (int i = 0; i < Arrlen(arrIndex) - 2; i++)
 75     {
 76         //arrIndex[4]未报错
 77         if ( i % Arrlen(arrIndex) < (Arrlen(arrIndex) - 2) && arrIndex[i] >= 1 && arrIndex[i + 1] >= 1 && arrIndex[i + 2] >= 1)
 78         {
 79             arrIndex[i] --; arrIndex[i + 1] --; arrIndex[i + 2] --;
 80             tempArr.push_back(SwitchToCardData(i));
 81             tempArr.push_back(SwitchToCardData(i+1));
 82             tempArr.push_back(SwitchToCardData(i+2));
 83
 84             GetWeaveItem(dep + 1);
 85
 86             arrIndex[i] ++; arrIndex[i + 1] ++; arrIndex[i + 2] ++;
 87             tempArr.pop_back();
 88             tempArr.pop_back();
 89             tempArr.pop_back();
 90
 91         }
 92     }
 93
 94 }
 95
 96 void main()
 97 {
 98     for (byte i=0;i < Arrlen(arr);i++)
 99     {
100         arrIndex[SwitchToCardIndex(arr[i])]++;
101     }
102
103     string str ="";
104     for (byte i = 0; i < Arrlen(arrIndex); i++)
105     {
106         stringstream stream;
107         stream<<(short)arrIndex[i];
108         str += " "+stream.str();
109     }
110
111     cout << str <<endl;
112
113     for (int i = 0; i < Arrlen(arrIndex); i++)
114     {
115         if (arrIndex[i] >= 2)//将牌
116         {
117             arrIndex[i] -= 2;
118             tempArr.push_back(SwitchToCardData(i));
119             tempArr.push_back(SwitchToCardData(i));
120
121             GetWeaveItem(0);
122
123             arrIndex[i] += 2;
124             tempArr.pop_back();
125             tempArr.pop_back();
126         }
127     }
128
129     system("pause");
130 }
时间: 2024-10-13 02:04:21

麻将回溯算法(无癞子)的相关文章

癞子麻将胡牌算法实现

最先实现的就是算法的实现. 需求:碰杠胡  ,不能吃 ,不能听 ,仅仅能自摸胡,当中癞子能够做随意牌可是不能碰和杠. 写的时候还不会玩麻将,还是老板教的.^_^ 最麻烦的是胡牌算法.之前搜到的都是不包括癞子正常的胡牌,用的是%3余2,当中余数2就是余的将的意思. 可是有癞子就不能这么用了.仅仅好自己写一个了. 一个有136张牌,万,饼,条,东西南北中发白34种牌. 有四个癞子是直接就胡牌的,最坏的情况是有3个癞子,可是假设遍历一遍不用逻辑推断就有34X34X34接近4万次. 想一下假设能胡牌,最

算法第五章 | 回溯算法

一. 回溯算法 回溯法有"通用的解题法"之称.可以系统地搜索一个问题的所有解或任一解,是一个既带有系统性又带有跳跃性的搜索算法. 它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树.算法搜索至解空间树的任一结点时,先判断该结点是否包含问题的解.如果肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯.否则,进入该子树,继续按深度优先策略搜索.回溯法求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束.回溯法求问题的一个解时,只要搜索到问题的一个解

五大算法之回溯算法

回溯算法是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”. 回溯法解决的问题可以用树结构来描述,每个状态下都对应有n种选择.以全排列问题为例,如对[1, 2, 3]进行全排列,每次从1, 2, 3中选择了一个值后,下一次又可以从1, 2, 3中选择一个值,将这个过程绘制成一棵树,每个节点都有1, 2, 3三个子节点.通常对树的遍历为

计科1111-1114班第一次实验作业(NPC问题——回溯算法、聚类分析)

实验课安排 地点: 科技楼423 时间:  计科3-4班---15周周一上午.周二下午 计科1-2班---15周周一下午.周二晚上(晚上时间从18:30-21:10) 请各班学委在实验课前飞信通知大家. 实验内容 (1)八皇后及N皇后问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即随意两个皇后都不能处于同一行.同一列或同一斜线上.问有多少种摆法. 高斯觉得有76种方案.1

c语言数据结构:递归的替代-------回溯算法

1.要理解回溯就必须清楚递归的定义和过程. 递归算法的非递归形式可采用回溯算法.主要考虑的问题在于: 怎样算完整的一轮操作. 执行的操作过程中怎样保存当前的状态以确保以后回溯访问. 怎样返回至上一次未执行的操作. 2.贴代码表现: 先序遍历二叉树: BTNode *FindNode(BTNode *b,ElementType x) { //在二叉树中查找值为x的结点 BTNode *p; if (b==NULL) return NULL; else if (b->Element==x) retu

穷举递归和回溯算法终结篇

穷举递归和回溯算法 在一般的递归函数中,如二分查找.反转文件等,在每个决策点只需要调用一个递归(比如在二分查找,在每个节点我们只需要选择递归左子树或者右子树),在这样的递归调用中,递归调用形成了一个线性结构,而算法的性能取决于调用函数的栈深度.比如对于反转文件,调用栈的深度等于文件的大小:再比如二分查找,递归深度为O(nlogn),这两类递归调用都非常高效. 现在考虑子集问题或者全排列问题,在每一个决策点我们不在只是选择一个分支进行递归调用,而是要尝试所有的分支进行递归调用.在每一个决策点有多种

第1次实验——NPC问题(回溯算法、聚类分析)

题目:八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 高斯认为有76种方案.1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果.计算机发明后,有多种方法可以解决此问题.     请编程实现八皇后问题,并把92种解的前三种解输出到屏幕(8*8的二维矩阵,Q代表皇后,X代

ACM/ICPC 之 最长公共子序列计数及其回溯算法(51Nod-1006(最长公共子序列))

这道题被51Nod定为基础题(这要求有点高啊),我感觉应该可以算作一级或者二级题目,主要原因不是动态规划的状态转移方程的问题,而是需要理解最后的回溯算法. 题目大意:找到两个字符串中最长的子序列,子序列的要求满足其中字符的顺序和字母在两个序列中都必须相同,任意输出一个符合题意的子序列 首先是最基本的最长公共子序列的状态转移问题: 这里的maxLen[i][j]数组的意思就是保存s1的前 i 个字符和s2的前 j 个字符匹配的状态. 举个例子:maxLen[3][6]即表明在s1的前3个字符和s2

从零开始学回溯算法

本文在写作过程中参考了大量资料,不能一一列举,还请见谅. 回溯算法的定义:回溯算法也叫试探法,它是一种系统地搜索问题的解的方法.回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试. 解题的一般步骤是: 1.定义一个解空间,它包含问题的解: 2.利用适于搜索的方法组织解空间: 3.利用深度优先法搜索解空间: 4.利用限界函数避免移动到不可能产生解的子空间. 问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性. 话不多说,我们来看几个具体的例子慢