DFS实践 - 简单版基础麻将胡牌所有可能

7 篇文章 0 订阅

参考

回溯算法团灭排列/组合/子集问题
回溯算法最佳实践:合法括号生成

麻将胡牌

麻将的牌, 出去春夏秋冬, 基本牌136张

颜色\值0x010x020x030x040x050x060x070x080x09
0x100x11/一万0x12/二万0x13/三万0x14/四万0x15/五万0x16/六万0x17/七万0x18/八万0x19/九万
0x200x21/一筒0x22/二筒0x23/三筒0x24/四筒0x25/五筒0x26/六筒0x27/七筒0x28/八筒0x29/九筒
0x300x31/一条0x32/二条0x33/三条0x34/四条0x35/五条0x36/六条0x37/七条0x38/八条0x39/九条
0x400x41/东0x42/南0x43/西0x44/北0x45/中0x46/发0x47/白————

找到麻将牌的一些规则

  1. 麻将牌有4种颜色
  2. 万筒条每个颜色有9个不同的值
  3. 每张牌都是4张
  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会增加浪费很多时间, 没考虑过影响性能这块

在这里插入图片描述
改成用引用
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值