Uva 131 - The Psychic Poker Player
题目链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=67
题目输入的每一行就是一个Case,前面五个表示你现在手上的牌,后面五个是放在桌上的牌,这五张牌叠在一起,牌面的值向下铺着,所以你看不到值,题目要你做的就是:你可以将你手中不要的牌拿走,可以是1张,2张...5张,当然你也可以不拿走。你从你手中的牌拿走多少张然后就从桌上的那些牌上从上到下取的方式拿走多少张,在这个的过程中,你要判断出你手中最好的牌的情况是什么,最终要把这种情况输出,这些情况在Sample中已经将所有的可能表示出来了,而且是有优先顺序的(即从上到下,上面的符合了下面的就不用判断了) 这些情况翻译成中文来就是:
//0 straight-flush 同花顺 == 一手同花的五张牌 + 五张牌点数连续的顺子
//1 four-of-a-kind 四张相同 的牌
//2 full-house 满堂红 三张同点牌加上一对
//3 flush 一手同花的五张牌
//4 straight 五张牌点数连续的顺子
//5 three-of-a-kind 三张相同的牌
//6 two-pairs 两对对子
//7 one-pair 一对对子
//8 highest-card 这个我也不知道,上面的所有情况不符合,那么就只有输出它了
为了找到最好的那种情况,你就必须从桌上分别拿:0, 1, 2, 3 ,4, 5张牌然后判断情况, 而拿了桌上的牌后(如果不为零)你就必须舍掉你手上现有的牌来替换它,然后来判断情况,比如说:你从桌上那1张牌,那么替换你手中的牌就有5种情况;你从桌上拿2张牌,你就要替换你手中的任意两张牌(C5取2中可能),等等
我的做法是:
Uva的上面的一题让我学到了位运算(如果不懂位运算,先看看我上一篇随笔),先不看桌上的牌,先想想替换你手中的牌的情况共有多少种?核心是这段代码:
for(int i=0; i<(1<<5); ++i)
{
int num = 0;
for(int j=0; j<5; ++j)
if(i&(1<<j)) num++;
}
先看 1<<j求出来的究竟是什么,从 0到4, 1<<j 的值为: 1, 10, 100, 1000, 10000 (每次都是这样)
而 i 的值呢? 从 0 到 1111,这时的 i 与 上五个不同值的(1<<j),得到的num表示 i 中有多少个 1, 如果 (i&(1<<j)) == true 的话,那么这时就说明 有 1 在 j 这个位置
i 所在的for结束后,那么纸牌的全部替换的情况都遍历了,尽管第一次可能替换你1张牌,第二次却替换你2张牌,第三次却又替换了你的1张牌,但位置时不同的,思考一下就会知道所有的情况在用上位运算后就很完美的处理掉了!
然后你要做的:
处理现在在你手中的牌,给牌排序,关键字有两个,牌值得大小和牌的花色,基数排序没必要,我就用了以前的方式,排完牌值大小的基础上再处理花色的问题。但在排牌之前最好先处理一下用字符代表牌的方式,转换成数字,比如说A=1, T=10, k=13; C = 1, S = ... 用类型为整型的二维数组存储一下,这样相对比较简单
牌的顺序排好后,这时就要看判断符合上面给的情况的那种了:
这就意味着要写8个判断的函数了(最后一种情况不要了,默认为最后一种情况),每个函数根据返回的值是1或0来判断
这样处理下去大概就差不多了, 需要注意的是:判断是否为顺子的时候,A可以放在第一位,也可以放在最后(即K的后面)
PS:
这次出的题目考虑得全面,并没有让做题者有疑惑或难堪的地方
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 char poke[12][4], temp[12][4]; 6 int transfer[6][2]; 7 char output[10][20]; 8 int res; 9 10 void memset_1(char (*des)[4], char (*src)[4]) 11 { 12 for(int i=0; i<10; i++) 13 strcpy(des[i], src[i]); 14 return; 15 } 16 17 int prior(char elem) 18 { 19 if('2'<= elem && elem <= '9') return (elem - '0'); 20 switch(elem) 21 { 22 case 'A' : return 1; 23 case 'T' : return 10; 24 case 'J' : return 11; 25 case 'Q' : return 12; 26 case 'K' : return 13; 27 28 case 'C' : return 1; 29 case 'D' : return 2; 30 case 'H' : return 3; 31 case 'S' : return 4; 32 } 33 return -1; 34 } 35 36 void swap_1(int left, int right) 37 { 38 int sw[2]; 39 sw[0] = transfer[left][0]; 40 sw[1] = transfer[left][1]; 41 transfer[left][0] = transfer[right][0]; 42 transfer[left][1] = transfer[right][1]; 43 transfer[right][0] = sw[0]; 44 transfer[right][1] = sw[1]; 45 return; 46 } 47 48 void basesort() 49 { 50 for(int i=0; i<5; ++i) 51 { 52 for(int j=0; j<=1; ++j) 53 transfer[i][j] = prior(temp[i][j]); 54 } 55 for(int i=0; i<4; ++i) 56 { 57 int flag = 0; 58 for(int j=0; j<4-i; ++j) 59 if(transfer[j][0] > transfer[j+1][0]) 60 { 61 swap_1(j, j+1); 62 flag = 1; 63 } 64 if(!flag) break; 65 } 66 for(int part1=0, part2=0, i=0; i<5; i++) 67 { 68 if(i+1<5 && transfer[i][0] == transfer[i+1][0]) 69 part2++; 70 else 71 { 72 for(int t=0; t<part2-part1; ++t) 73 { 74 int flag = 0; 75 for(int j=part1; j<part2-t; ++j) 76 if(transfer[j][1] > transfer[j+1][1]) 77 { 78 swap_1(j, j+1); 79 flag = 1; 80 } 81 if(!flag) break; 82 } 83 part1 = part2 = i+1; 84 } 85 } 86 return; 87 } 88 89 void Print() 90 { 91 for(int i=0; i<5; ++i) 92 cout<<temp[i]<<" "; 93 return; 94 } 95 96 int is_straight_flush() 97 { 98 int flag = 1; 99 for(int i=1; i<5; ++i) 100 { 101 if(transfer[i-1][0]+1 != transfer[i][0] || transfer[i-1][1] != transfer[i][1]) 102 { 103 flag = 0; 104 break; 105 } 106 } 107 if(flag) return 1; 108 else 109 { 110 if(transfer[0][0] == 1 && transfer[1][0] == 10 && transfer[0][1] == transfer[1][1]) 111 { 112 flag = 1; 113 for(int i=2; i<5; ++i) 114 if(transfer[i-1][0]+1 != transfer[i][0] || transfer[i-1][1] != transfer[i][1]) 115 { 116 flag = 0; 117 break; 118 } 119 } 120 return flag; 121 } 122 } 123 124 int is_four() 125 { 126 for(int i=0; i<=1; ++i) 127 { 128 int flag = 1; 129 for(int j=i+1; j<4+i; ++j) 130 { 131 if(transfer[j][0] != transfer[j-1][0]) 132 { 133 flag = 0; 134 break; 135 } 136 } 137 if(flag) return 1; 138 } 139 return 0; 140 141 } 142 143 int is_full() 144 { 145 if(transfer[0][0] == transfer[1][0] && transfer[3][0] == transfer[4][0]) 146 { 147 if(transfer[1][0] == transfer[2][0] || transfer[2][0] == transfer[3][0]) 148 return 1; 149 } 150 return 0; 151 } 152 153 int is_flush() 154 { 155 for(int i=1; i<5; ++i) 156 if(transfer[i-1][1] != transfer[i][1]) 157 return 0; 158 return 1; 159 } 160 161 int is_straight() 162 { 163 int flag = 1; 164 for(int i=1; i<5; ++i) 165 if(transfer[i-1][0]+1 != transfer[i][0]) 166 { 167 flag = 0; 168 break; 169 } 170 if(flag) return 1; 171 else 172 { 173 if(transfer[0][0] == 1 && transfer[1][0] == 10) 174 { 175 flag = 1; 176 for(int i=2; i<5; ++i) 177 if(transfer[i-1][0] != transfer[i][0]) 178 { 179 flag = 0; 180 break; 181 } 182 } 183 return flag; 184 } 185 } 186 187 int is_three() 188 { 189 for(int i=0; i<=2; ++i) 190 { 191 if(transfer[i][0] == transfer[i+1][0] && transfer[i+1][0] == transfer[i+2][0]) 192 return 1; 193 } 194 return 0; 195 } 196 197 int is_two() 198 { 199 if(transfer[0][0] == transfer[1][0]) 200 { 201 if(transfer[2][0] == transfer[3][0] || transfer[3][0] == transfer[4][0]) 202 return 1; 203 } 204 if(transfer[1][0] == transfer[2][0] && transfer[3][0] == transfer[4][0]) 205 return 1; 206 return 0; 207 } 208 209 int is_one() 210 { 211 for(int i=0; i<=3; ++i) 212 { 213 if(transfer[i][0] == transfer[i+1][0]) return 1; 214 } 215 return 0; 216 } 217 218 void Traverse() 219 { 220 basesort(); 221 222 if(is_straight_flush()) {res = 0; return;} 223 if(is_four()) {res = 1; return;} 224 if(is_full()) {res = res < 2 ? res : 2; return;} 225 if(is_flush()) {res = res < 3 ? res : 3; return;} 226 if(is_straight()) {res = res < 4 ? res : 4; return;} 227 if(is_three()) {res = res < 5 ? res : 5; return;} 228 if(is_two()) {res = res < 6 ? res : 6; return;} 229 if(is_one()) {res = res < 7 ? res : 7; return;} 230 } 231 232 void memset_2() 233 { 234 strcpy(output[0], "straight-flush"); 235 strcpy(output[1], "four-of-a-kind"); 236 strcpy(output[2], "full-house"); 237 strcpy(output[3], "flush"); 238 strcpy(output[4], "straight"); 239 strcpy(output[5], "three-of-a-kind"); 240 strcpy(output[6], "two-pairs"); 241 strcpy(output[7], "one-pair"); 242 strcpy(output[8], "highest-card"); 243 } 244 245 int main() 246 { 247 /* freopen("input.txt", "r", stdin); 248 freopen("output.txt", "w", stdout); 249 */ 250 int sequence[6]; 251 for(int r=0; r<6; r++) sequence[r] = r+1; 252 memset_2(); 253 while(cin>>poke[0]) 254 { 255 for(int i=2; i<=10; ++i) 256 cin>>poke[i-1]; 257 res = 8; 258 for(int i=0; i<(1<<5); ++i) 259 { 260 int num = 0; 261 memset_1(temp, poke); 262 for(int j=0; j<5; ++j) 263 if(i&(1<<j)) num++; 264 sort(sequence, sequence+6); 265 int cnt=0; 266 for(int j=0; j<5; ++j) 267 if(i&(1<<j)) strcpy(temp[j], temp[(sequence[cnt++]+4)]); 268 Traverse(); 269 if(res == 0) break; 270 } 271 cout<<"Hand: "; 272 for(int i=0; i<5; ++i) 273 cout<<poke[i]<<" "; 274 cout<<"Deck: "; 275 for(int i=5; i<10; ++i) 276 cout<<poke[i]<<" "; 277 cout<<"Best hand: "; 278 cout<<output[res]<<endl; 279 } 280 return 0; 281 }
更多内容请关注个人微信公众号 物役记 (微信号:materialchains)