HDU 4431 Mahjong(枚举+模拟)(2012 Asia Tianjin Regional Contest)

Problem Description
Japanese Mahjong is a four-player game. The game needs four people to sit around a desk and play with a set of Mahjong tiles. A set of Mahjong tiles contains four copies of the tiles described next:

One to nine Man, which we use 1m to 9m to represent;

One to nine Sou, which we use 1s to 9s to represent;

One to nine Pin, which we use 1p to 9p to represent;

Character tiles, which are:Ton, Nan, Sei, Pei, Haku, Hatsu, Chun, which we use 1c to 7c to represent.

A winning state means a set of 14 tiles that normally contains a pair of same tiles (which we call "eyes") and four melds. A meld is formed by either three same tiles(1m, 1m, 1m or 2c, 2c, 2c for example) or three continuous non-character tiles(1m, 2m, 3m or 5s, 6s, 7s for example).

However, there are two special winning states that are different with the description above, which are:
"Chii Toitsu", which means 7 different pairs of tiles;
"Kokushi Muso", which means a set of tiles that contains all these tiles: 1m, 9m, 1p, 9p, 1s, 9s and all 7 character tiles. And the rest tile should also be one of the 13 tiles above.

And the game starts with four players receiving 13 tiles. In each round every player must draw one tile from the deck one by one. If he reaches a winning state with these 14 tiles, he can say "Tsu Mo" and win the game. Otherwise he should discard one of his 14 tiles. And if the tile he throws out can form a winning state with the 13 tiles of any other player, the player can say "Ron" and win the game.

Now the question is, given the 13 tiles you have, does there exist any tiles that can form a winning state with your tiles?

(Notes: Some of the pictures and descriptions above come from Wikipedia.)
 
Input
The input data begins with a integer T(1≤T≤20000). Next are T cases, each of which contains 13 tiles. The description of every tile is as above.
 
Output
For each cases, if there actually exists some tiles that can form a winning state with the 13 tiles given, print the number first and then print all those tiles in order as the description order of tiles above. Otherwise print a line "Nooten"(without quotation marks).
 
题目大意:给你十三张麻将牌,问你再加一张什么牌,可以胡。胡的方法:1、有一对眼,剩下的是顺子和三张相同的牌组成14张牌。2、有7个对子(4个相同的牌不能算两对,这个题目似乎没有说,就是看漏了这个条件WA了一个多小时……我就说怎么题目说两个我只看到一个呢……)。3、十三幺。
思路:枚举每一张牌,判断能否获胜。条件2、3特判即可。对于条件1,如果有某张字牌只有1张或4张,或有两个以上的字牌有2张,输出错误。然后枚举眼(对子),然后对每一种牌(万子、筒子、束子)分配从1~9循环,若某张牌 i 剩下3张或以上,那么把三张 i 作为三个相同的牌拿掉(如果这牌是能获胜的,那么枚举到 i ,i 前面的牌都已经被判断后拿掉了,那么如果 i 可以作为顺子被拿掉,那么 i+1 和 i+2 肯定都有3张或以上)。若小于三张,则把 i 、 i+1 、 i+2 拿掉。如果拿不掉则判断不能获胜。全部拿掉之后判断获胜。那些TLE的人肯定是姿势不对。
 
代码(265MS):
  1 #include <cstdio>

  2 #include <iostream>

  3 #include <algorithm>

  4 #include <cstring>

  5 #include <vector>

  6 using namespace std;

  7 typedef long long LL;

  8 

  9 const int MAXN = 13;

 10 

 11 struct TILES {

 12     int P[MAXN], M[MAXN], S[MAXN], C[MAXN];

 13 

 14     void init() {

 15         #define CL(a) memset(a, 0, sizeof(a))

 16         CL(P), CL(M), CL(S), CL(C);

 17     }

 18 

 19     void read() {

 20         char str[5];

 21         for(int i = 0; i < 13; ++i) {

 22             scanf("%s", str);

 23             switch(str[1]) {

 24                 case 'p':++P[str[0] - '0'];break;

 25                 case 'm':++M[str[0] - '0'];break;

 26                 case 's':++S[str[0] - '0'];break;

 27                 case 'c':++C[str[0] - '0'];break;

 28             }

 29         }

 30     }

 31 

 32     bool special_judge1() {

 33         int cnt = 0;

 34         for(int i = 1; i <= 9; ++i) {

 35             cnt += (M[i] == 2);

 36             cnt += (S[i] == 2);

 37             cnt += (P[i] == 2);

 38             cnt += (C[i] == 2);

 39         }

 40         return cnt == 7;

 41     }

 42 

 43     bool special_judge2() {

 44         bool eyes = false;

 45         for(int i = 1; i <= 7; ++i) {

 46             if(C[i] == 0 || C[i] > 2) return false;

 47             if(C[i] == 2) eyes = true;

 48         }

 49         if(M[1] == 0 || M[1] > 2) return false;

 50         if(M[9] == 0 || M[9] > 2) return false;

 51         if(S[1] == 0 || S[1] > 2) return false;

 52         if(S[9] == 0 || S[9] > 2) return false;

 53         if(P[1] == 0 || P[1] > 2) return false;

 54         if(P[9] == 0 || P[9] > 2) return false;

 55         if(M[1] == 2 || M[9] == 2) eyes = true;

 56         if(S[1] == 2 || S[9] == 2) eyes = true;

 57         if(P[1] == 2 || P[9] == 2) eyes = true;

 58         return eyes;

 59     }

 60 

 61     int UP[MAXN], UM[MAXN], US[MAXN];

 62 

 63     bool isWin() {

 64         int x;

 65         for(int i = 1; i <= 9; ++i) {

 66             if(P[i] - UP[i] >= 3) UP[i] += 3;

 67             if(S[i] - US[i] >= 3) US[i] += 3;

 68             if(M[i] - UM[i] >= 3) UM[i] += 3;

 69             x = P[i] - UP[i];

 70             if(x != 0) {

 71                 UP[i] += x;

 72                 if((UP[i + 1] += x) > P[i + 1]) return false;

 73                 if((UP[i + 2] += x) > P[i + 2]) return false;

 74             }

 75             x = S[i] - US[i];

 76             if(x != 0) {

 77                 US[i] += x;

 78                 if((US[i + 1] += x) > S[i + 1]) return false;

 79                 if((US[i + 2] += x) > S[i + 2]) return false;

 80             }

 81             x = M[i] - UM[i];

 82             if(x != 0) {

 83                 UM[i] += x;

 84                 if((UM[i + 1] += x) > M[i + 1]) return false;

 85                 if((UM[i + 2] += x) > M[i + 2]) return false;

 86             }

 87         }

 88         return true;

 89     }

 90 

 91     bool judge() {

 92         if(special_judge1() || special_judge2()) return true;

 93         bool eyes = false;

 94         for(int i = 1; i <= 7; ++i) {

 95             if(C[i] == 2) {

 96                 if(!eyes) eyes = true;

 97                 else return false;

 98             }

 99             if(C[i] == 1 || C[i] == 4) return false;

100         }

101         if(eyes) {

102             CL(UP), CL(UM), CL(US);

103             return isWin();

104         }

105         for(int i = 1; i <= 9; ++i) {

106             if(P[i] >= 2) {

107                 CL(UP), CL(UM), CL(US);

108                 UP[i] = 2;

109                 if(isWin()) return true;

110             }

111         }

112         for(int i = 1; i <= 9; ++i) {

113             if(S[i] >= 2) {

114                 CL(UP), CL(UM), CL(US);

115                 US[i] = 2;

116                 if(isWin()) return true;

117             }

118         }

119         for(int i = 1; i <= 9; ++i) {

120             if(M[i] >= 2) {

121                 CL(UP), CL(UM), CL(US);

122                 UM[i] = 2;

123                 if(isWin()) return true;

124             }

125         }

126         return false;

127     }

128 

129     vector<int> ans2;

130     vector<char> ans1;

131 

132     void solve() {

133         ans1.clear();

134         ans2.clear();

135         for(int i = 1; i <= 9; ++i) {

136             ++M[i];

137             if(M[i] <= 4 && judge()) {

138                 ans1.push_back('m');

139                 ans2.push_back(i);

140             }

141             --M[i];

142         }

143         for(int i = 1; i <= 9; ++i) {

144             ++S[i];

145             if(S[i] <= 4 && judge()) {

146                 ans1.push_back('s');

147                 ans2.push_back(i);

148             }

149             --S[i];

150         }

151         for(int i = 1; i <= 9; ++i) {

152             ++P[i];

153             if(P[i] <= 4 && judge()) {

154                 ans1.push_back('p');

155                 ans2.push_back(i);

156             }

157             --P[i];

158         }

159         for(int i = 1; i <= 7; ++i) {

160             ++C[i];

161             if(C[i] <= 4 && judge()) {

162                 ans1.push_back('c');

163                 ans2.push_back(i);

164             }

165             --C[i];

166         }

167     }

168 

169     void print() {

170         int len = ans1.size();

171         if(len == 0) {

172             puts("Nooten");

173             return ;

174         }

175         printf("%d", len);

176         for(int i = 0; i < len; ++i)

177             printf(" %d%c", ans2[i], ans1[i]);

178         puts("");

179     }

180 } G;

181 

182 int main() {

183     int T;

184     scanf("%d", &T);

185     while(T--) {

186         G.init();

187         G.read();

188         G.solve();

189         G.print();

190     }

191 }
View Code

 

你可能感兴趣的:(test)