题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930
解题报告:斗地主,加了一个四张可以带两张不一样的牌,也可以带一对,判断打出一手牌之后,如果对手没有能够大过你的牌就输出Yes,或者如果你把手上的牌一次性打完也输出Yes,否则输出No,代码有280多行,表示光是敲代码就花了一个多小时,手速还是太慢。
1、首先判断手上的牌能不能一次打完
如果一次性打不完:
2、首先判断对方有没有一对王,有就输出No
3、判断对手有没有四张的牌,如果有,再判断自己有没有四张的牌,如果对手有自己没有就是输,如果自己有对手没有自己有就是赢,如果两个人都有就看谁的更大,如果两个人都没有,则继续判断
4、最后一步,尝试将自己的牌组合成前面的六种打法打出去,然后判断对手有没有可以大过自己的牌,如果有就继续判断,如果没有就是赢。
详细情况看代码吧,有详细的注释。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<deque> 6 using namespace std; 7 8 void exchto(char* str,int* num) //先把输入预处理成各种牌的张数num[i]表示第i大的牌有多少张 9 { 10 int len = strlen(str); 11 for(int i = 0;i < len;++i) 12 { 13 if(str[i] >= '3' && str[i] <= '9') 14 num[str[i]-'0'-2]++; 15 if(str[i] == 'T') num[8]++; 16 if(str[i] == 'J') num[9]++; 17 if(str[i] == 'Q') num[10]++; 18 if(str[i] == 'K') num[11]++; 19 if(str[i] == 'A') num[12]++; 20 if(str[i] == '2') num[13]++; 21 if(str[i] == 'X') num[14]++; 22 if(str[i] == 'Y') num[15]++; 23 } 24 } 25 int judge_once(const int* num) //判断能否一次打完或者自己有Nuke的情况 26 { 27 if(num[14] && num[15]) //Nuke 28 return 1; 29 int n = 0; 30 for(int i = 1;i <= 15;++i) 31 if(num[i] != 0) n++; 32 if(n > 3) return 0; //牌种类数大于3不可能一次打完 33 if(n == 1) return 1; //等于1一定可以一次打完 34 if(n == 2) 35 { 36 for(int i = 1;i <= 13;++i) 37 for(int j = 1;j < i;++j) 38 { 39 if(num[i] == 3 && num[j] >= 1 && num[j] <= 2) 40 return 1; 41 if(num[j] == 3 && num[i] >= 1 && num[i] <= 2) 42 return 1; 43 if(num[i] == 4 && num[j] == 2) 44 return 1; 45 if(num[j] == 4 && num[i] == 2) 46 return 1; 47 } 48 } 49 else if(n == 3) 50 { 51 int flag = -1; 52 for(int i = 1;i <= 13;++i) 53 if(num[i] == 4 && flag == -1) flag = 1; 54 else if(num[i] == 4 && flag == 1) flag = 0; 55 if(flag <= 0) return 0; //没有4或者有多个4张的,不行 56 int m = 0; 57 for(int i = 1;i <= 13;++i) 58 if(num[i] == 1) m++; 59 if(m == 2) return 1; 60 return 0; 61 } 62 return 0; 63 } 64 int judge_have4(const int* num1,const int* num2) //判断双方是否存在4 65 { 66 int a = 16,b = 16; 67 for(int i = 13;i >= 1;--i) 68 if(num1[i] == 4) 69 { 70 a = i; 71 break; 72 } 73 for(int i = 13;i >= 1;--i) 74 if(num2[i] == 4) 75 { 76 b = i; 77 break; 78 } 79 if(b != 16 && a == 16) return -1; //对手有4而自己没有4张的情况 80 if(a != 16 && b == 16) return 1; //自己有4而对手没四 81 if(a == 16 && b == 16) return 0; 82 if(a >= b) return 1; 83 else if(a < b) return -1; 84 } 85 /////////下面尝试前六种不同的打法,如果可以用该打法赢,返回1,否则返回0 86 int judge1(const int* num1,const int* num2) 87 { 88 int a = 16,b = 16; 89 for(int i = 15;i >= 1;--i) 90 if(num1[i] != 0) 91 { 92 a = i; 93 break; 94 } 95 for(int i = 15;i >= 1;--i) 96 if(num2[i] != 0) 97 { 98 b = i; 99 break; 100 } 101 return a >= b; //因为双方至少有一张牌,否则要判断是否有没找到的情况 102 } 103 int judge2(const int* num1,const int* num2) 104 { 105 int a = 16,b = 16; 106 for(int i = 15;i >= 1;--i) 107 if(num1[i] >= 2) 108 { 109 a = i; 110 break; 111 } 112 for(int i = 15;i >= 1;--i) 113 if(num2[i] >= 2) 114 { 115 b = i; 116 break; 117 } 118 if(a != 16 && b == 16) return 1; 119 if(a == 16 && b == 16) return 0; 120 if(a != 16 && b != 16) return a >= b; 121 return 0; 122 } 123 int judge3(const int* num1,const int* num2) 124 { 125 int a = 16,b = 16; 126 for(int i = 15;i >= 1;--i) 127 if(num1[i] >= 3) 128 { 129 a = i; 130 break; 131 } 132 for(int i = 15;i >= 1;--i) 133 if(num2[i] >= 3) 134 { 135 b = i; 136 break; 137 } 138 if(a != 16 && b == 16) return 1; 139 if(a == 16 && b == 16) return 0; 140 if(a != 16 && b != 16) return a >= b; 141 return 0; 142 } 143 int judge4(const int* num1,const int* num2) 144 { 145 int a = 16,b = 16,c = 0,d = 0; 146 for(int i = 15;i >= 1;--i) 147 if(num1[i] >= 3) 148 { 149 a = i; 150 break; 151 } 152 for(int i = 15;i >= 1;--i) 153 if(num2[i] >= 3) 154 { 155 b = i; 156 break; 157 } 158 if(a != 16) 159 for(int i = 1;i <= 15;++i) 160 if(i != a && num1[i] != 0) 161 { 162 c = 1; 163 break; 164 } 165 if(b != 16) 166 for(int i = 1;i <= 15;++i) 167 if(i != b && num2[i] != 0) 168 { 169 d = 1; 170 break; 171 } 172 if(a != 16 && c == 1 && (b == 16 || d == 0)) return 1; //当对手有三个但没有1个另外的也不满足这种打法 173 if(a == 16 && b == 16) return 0; 174 if(a != 16 && b != 16 && c == 1 && d == 1) return a >= b; 175 return 0; 176 } 177 int judge5(const int* num1,const int* num2) 178 { 179 int a = 16,b = 16,c = 0,d = 0; 180 for(int i = 15;i >= 1;--i) 181 if(num1[i] >= 3) 182 { 183 a = i; 184 break; 185 } 186 for(int i = 15;i >= 1;--i) 187 if(num2[i] >= 3) 188 { 189 b = i; 190 break; 191 } 192 if(a != 16) 193 for(int i = 1;i <= 15;++i) 194 if(i != a && num1[i] >= 2) 195 { 196 c = 1; 197 break; 198 } 199 if(b != 16) 200 for(int i = 1;i <= 15;++i) 201 if(i != b && num2[i] >= 2) 202 { 203 d = 1; 204 break; 205 } 206 if(a != 16 && c == 1 && (b == 16 || d == 0)) return 1; //当对手有三个但没有1个另外的也不满足这种打法 207 if(a == 16 && b == 16) return 0; 208 if(a != 16 && b != 16 && c == 1 && d == 1) return a >= b; 209 return 0; 210 } 211 int judge6(const int* num1,const int* num2) 212 { 213 int a = 16,b = 16,c = 0,d = 0; 214 for(int i = 15;i >= 1;--i) 215 if(num1[i] >= 4) 216 { 217 a = i; 218 break; 219 } 220 for(int i = 15;i >= 1;--i) 221 if(num2[i] >= 4) 222 { 223 b = i; 224 break; 225 } 226 if(a != 16) 227 for(int i = 1;i <= 15;++i) 228 if(i != a && num1[i] >= 1) 229 c++; 230 if(b != 16) 231 for(int i = 1;i <= 15;++i) 232 if(i != b && num2[i] >= 1) 233 d++; 234 if(a != 16 && c >= 2 && b == 16) return 1; 235 if(a == 16 && b == 16) return 0; 236 if(a != 16 && b != 16 && c >= 2 && d >= 2) return a >= b; 237 return 0; 238 } 239 240 int main() 241 { 242 // freopen("1003.txt","r",stdin); 243 // freopen("out1.txt","w",stdout); 244 int T; 245 246 char one[20],two[20]; 247 int num1[20],num2[20]; 248 scanf("%d",&T); 249 while(T--) 250 { 251 scanf("%s%s",one,two); 252 memset(num1,0,sizeof(num1)); 253 memset(num2,0,sizeof(num2)); 254 exchto(one,num1); 255 exchto(two,num2); 256 if(judge_once(num1)) //判断能否一次打完 257 { 258 puts("Yes"); 259 continue; 260 } 261 if(num2[14] && num2[15]) //对手有Nuke直接输 262 { 263 puts("No"); 264 continue; 265 } 266 int tt1 = judge_have4(num1,num2); //判断双方是否存在4 267 ///////直接赢返回1,直接输返回-1,还有希望返回0 268 if(tt1 == 1 || tt1 == -1) //可以判断出结果 269 { 270 printf(tt1 == 1? "Yes ":"No "); 271 continue; 272 } 273 /////////下面尝试前六种不同的打法,如果可以用该打法赢,返回1,否则返回0 274 int flag = 0; 275 flag = max(flag,judge1(num1,num2)); 276 flag = max(flag,judge2(num1,num2)); 277 flag = max(flag,judge3(num1,num2)); 278 flag = max(flag,judge4(num1,num2)); 279 flag = max(flag,judge5(num1,num2)); 280 flag = max(flag,judge6(num1,num2)); 281 printf(flag? "Yes ":"No "); 282 } 283 return 0; 284 }