首页 > 代码库 > HDU 4930 Fighting the Landlords(模拟)

HDU 4930 Fighting the Landlords(模拟)

题目链接: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);  //判断双方是否存在4267         ///////直接赢返回1,直接输返回-1,还有希望返回0 268         if(tt1 == 1 || tt1 == -1)    //可以判断出结果 269         {270             printf(tt1 == 1? "Yes\n":"No\n");271             continue;272         }273         /////////下面尝试前六种不同的打法,如果可以用该打法赢,返回1,否则返回0274         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\n":"No\n");282     }283     return 0;284 }        
View Code