参考
回溯算法团灭排列/组合/子集问题
回溯算法最佳实践:合法括号生成
麻将胡牌
麻将的牌, 出去春夏秋冬, 基本牌136张
颜色\值 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 |
---|---|---|---|---|---|---|---|---|---|
0x10 | 0x11/一万 | 0x12/二万 | 0x13/三万 | 0x14/四万 | 0x15/五万 | 0x16/六万 | 0x17/七万 | 0x18/八万 | 0x19/九万 |
0x20 | 0x21/一筒 | 0x22/二筒 | 0x23/三筒 | 0x24/四筒 | 0x25/五筒 | 0x26/六筒 | 0x27/七筒 | 0x28/八筒 | 0x29/九筒 |
0x30 | 0x31/一条 | 0x32/二条 | 0x33/三条 | 0x34/四条 | 0x35/五条 | 0x36/六条 | 0x37/七条 | 0x38/八条 | 0x39/九条 |
0x40 | 0x41/东 | 0x42/南 | 0x43/西 | 0x44/北 | 0x45/中 | 0x46/发 | 0x47/白 | —— | —— |
找到麻将牌的一些规则
- 麻将牌有4种颜色
- 万筒条每个颜色有9个不同的值
- 每张牌都是4张
- 胡牌的格式是 3 3 3 3 2, 也就是4个刻子或者是4个顺子, 或者是4个刻子和顺子混搭
拆分子问题, 每种颜色所有胡牌的可能
子问题
在[0, 0, 0, 0, 0, 0, 0 , 0, 0] 9个空位用一个数字3或者 [1, 1, 1] 填, 每个空位不能超过4(大于4), 选择次数不能超过4(大于4), 找出所有情况
思路
最多选择4次, 每次选择方式有16种, 到达n=4的时候进行回溯, 遍历所有
#include<iostream>
#include<vector>
#include<string>
#include<unordered_map>
#include <fstream>
#include <map>
using namespace std;
bool IsExist(map<int,int>& a, int b)
{
if (a[b] == 0)
{
return false;
}
return true;
}
static map<int,int> m;
static vector<int> pLists;
// [0,0,0,0,0,0,0,0,0]
// 所有胡的可能
void dfsHu(vector<int> nums, int needCount, int& count)
{
if (needCount > 3)
{
return;
}
for (int i = 0; i <= 15; i++)
{
count++;
if (i <= 8)
{
if (nums[i] > 1)
{
continue;
}
nums[i] += 3;
}
else
{
int index = i - 9;
if (nums[index] >= 4 || nums[index + 1] >= 4 || nums[index + 2] >= 4)
{
continue;
}
nums[index] += 1;
nums[index + 1] += 1;
nums[index + 2] += 1;
}
int keyNum = 0;
for (int j = 0; j < 9; j++)
{
keyNum = keyNum * 10 + nums[j];
}
if (IsExist(m, keyNum)== false)
{
m.insert(make_pair(keyNum,1));
pLists.push_back(keyNum);
}
dfsHu(nums, needCount + 1, count);
if (i <= 8)
{
nums[i] -= 3;
}
else
{
int index = i - 9;
nums[index] -= 1;
nums[index + 1] -= 1;
nums[index + 2] -= 1;
}
}
}
int main()
{
vector<int> nums = { 0,0,0,0,0,0,0,0,0 };
int a = 0;
dfsHu(nums, 0, a);
ofstream mycout("temp.txt");
for (int i = 0; i < numsLists.size(); i++)
{
mycout << numsLists[i] << endl;
}
mycout.close();
system("pause");
return 0;
}
详细
https://blog.csdn.net/zbbzb/article/details/90516141
遇到的问题
c++版本的发现速度很慢, 比python版本慢很多, 这完全不可能, 一开始以为是push_back 或者是 insert 很耗时, 后来发现是去重函数用的是拷贝赋值耗时, 应该直接引用, 这个地方是要注意
要把map中的数据从新拷贝, 特别是map会增加浪费很多时间, 没考虑过影响性能这块
改成用引用