uva 11210 - Chinese Mahjong(暴力搜索)
2016-12-05 15:04
375 查看
这道题目是《算法竞赛入门经典训练指南》第1章算法设计基础的例9,看起来有点麻烦,最近开始学打麻将,比较好的理解了这道题的意思,之前一直都不能理解题意。
有了一定的麻将胡牌基础,这道题很容易理解。胡牌规则很简单,一个将(两个一样),3个顺子(3个同花相连的牌)或刻子(3张相同的牌)即可胡牌。题目的要求是给13 张牌判断是否已经听牌,即再有一张某种花色牌即可胡牌。如果是,输出需要哪一种花色牌即可胡牌,如果不是输出not ready。
算法的大致思路,首先枚举34种花色牌,表示有这种花色的牌可以胡牌(如果这种花色牌在13张中已经有4张,则跳过)。现在即有14张牌,对于这14张牌,再枚举34张种花色牌,表示有这种花色的两张牌则作为将,再对剩下12张牌进行操作。
剩下的12张牌使用dfs,及当搜索4次时,若果都符合则可以听牌。剩下的12张牌,依旧是枚举34种花色牌,先找这种花色是否有至少3张牌,如果有,则构成顺子,再继续搜索。如果没有则判断这张牌和与它后面相连的2张牌能否构成刻子,若可以,则构成刻子,再继续搜索。如果不能,则表示没有听牌,则跳出dfs,继续枚举将牌。需要注意的是Dong,Nan,Xi,Bei,Zhong,Fa,Bai都不能构成刻子。
存储方式则是先用一个二维字符数组存下所有的麻将花色,再用一维数组通过预处理13张牌保存下13张各种花色的牌各有多少张。
注意:《算法竞赛入门经典训练指南》上给的程序个人感觉有点小问题。在枚举将牌和搜索顺子、刻子的两个函数里,每当成功找到时直接返回true但是并没有将之前减掉的牌数加回,这样容易造成只能找到一个能够听牌的花色,剩下的花色找不出来,所以在每个return true之前都需要添加上牌数加回的代码。
有了一定的麻将胡牌基础,这道题很容易理解。胡牌规则很简单,一个将(两个一样),3个顺子(3个同花相连的牌)或刻子(3张相同的牌)即可胡牌。题目的要求是给13 张牌判断是否已经听牌,即再有一张某种花色牌即可胡牌。如果是,输出需要哪一种花色牌即可胡牌,如果不是输出not ready。
算法的大致思路,首先枚举34种花色牌,表示有这种花色的牌可以胡牌(如果这种花色牌在13张中已经有4张,则跳过)。现在即有14张牌,对于这14张牌,再枚举34张种花色牌,表示有这种花色的两张牌则作为将,再对剩下12张牌进行操作。
剩下的12张牌使用dfs,及当搜索4次时,若果都符合则可以听牌。剩下的12张牌,依旧是枚举34种花色牌,先找这种花色是否有至少3张牌,如果有,则构成顺子,再继续搜索。如果没有则判断这张牌和与它后面相连的2张牌能否构成刻子,若可以,则构成刻子,再继续搜索。如果不能,则表示没有听牌,则跳出dfs,继续枚举将牌。需要注意的是Dong,Nan,Xi,Bei,Zhong,Fa,Bai都不能构成刻子。
存储方式则是先用一个二维字符数组存下所有的麻将花色,再用一维数组通过预处理13张牌保存下13张各种花色的牌各有多少张。
注意:《算法竞赛入门经典训练指南》上给的程序个人感觉有点小问题。在枚举将牌和搜索顺子、刻子的两个函数里,每当成功找到时直接返回true但是并没有将之前减掉的牌数加回,这样容易造成只能找到一个能够听牌的花色,剩下的花色找不出来,所以在每个return true之前都需要添加上牌数加回的代码。
#include <iostream> #include "stdio.h" #include "string.h" using namespace std; int n[35]; char mj[35][6] = {"1T", "2T", "3T", "4T", "5T", "6T", "7T", "8T", "9T", "1S", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "1W", "2W", "3W", "4W", "5W", "6W", "7W", "8W", "9W", "DONG", "NAN", "XI", "BEI", "ZHONG", "FA", "BAI" }; void convert(char a[]) { int i; for(i = 0; i < 34; i++) if(!strcmp(mj[i], a)) n[i]++; } bool sear(int tmp, int j, int k) { int i; for(i = 0; i < 34; i++) { if(n[i] == 3) { if(tmp == 3) return true; n[i] -= 3; if(sear(tmp + 1, j, k)) { n[i] += 3; return true; } else n[i] += 3; } if(i < 27 && i % 9 < 7 && n[i] > 0 && n[i + 1] > 0 && n[i + 2] > 0) { if(tmp == 3) return true; n[i]--; n[i + 1]--; n[i + 2]--; if(sear(tmp + 1, j, k)) { n[i]++; n[i + 1]++; n[i + 2]++; return true; } else { n[i]++; n[i + 1]++; n[i + 2]++; } } if(n[i] > 0) return false; } return false; } bool jiang(int tmp) { int i; for(i = 0; i < 34; i++) { if(n[i] > 1) { n[i] -= 2; if(sear(0, tmp, i)) { n[i] += 2; return true; } else n[i] += 2; } } return false; } int main() { int i, f, cas = 0; char a[6]; while(~scanf("%s", a)) { if(a[0] == '0') break; memset(n, 0, sizeof(n)); convert(a); for(i = 1; i < 13; i++) { scanf("%s", a); convert(a); } f = 1; printf("Case %d:", ++cas); for(i = 0; i < 34; i++) { if(n[i] == 4) continue; n[i]++; if(jiang(i)) { printf(" %s", mj[i]); f = 0; } n[i]--; } if(f) printf(" Not ready"); printf("\n"); } return 0; }
相关文章推荐
- uva 11210 Chinese Mahjong(暴力搜索)
- UVA - 11210 Chinese Mahjong(注意暴力搜索时排除排列重复搜索)
- uva 11210 - Chinese Mahjong 暴力回溯
- uva 11210 Chinese Mahjong(暴力枚举)
- UVA 11210 - Chinese Mahjong(暴力枚举)
- UVa 11210 Chinese Mahjong (暴力,递归寻找)
- UVALive 5107 dfs暴力搜索
- UVA 12649 Folding Machine(暴力搜索)
- UVA-11210-Chinese Mahjong
- uva11210 Chinese Mahjong
- UVA 11210 - Chinese Mahjong
- 【暴力搜索】[UVa 11212]Editing a Book
- UVA 11210 [Chinese Mahjong]
- 枚举,搜索(中国麻将,uva 11210)
- uva 11210 - Chinese Mahjong
- UVA 11210 Chinese Mahjong
- Uva 11210 - Chinese Mahjong
- UVa 11210 Chinese Mahjong (模拟&枚举&回溯)
- hdu 4431 Mahjong,uva 11210 chinese Mahjong,麻将,超快的解法。。
- uva 11210 - Chinese Mahjong(模拟,3级)