设为首页 加入收藏

TOP

UVA-11210-Chinese Mahjong
2015-07-20 17:15:11 来源: 作者: 【 】 浏览:2
Tags:UVA-11210-Chinese Mahjong

训练指南24页的题 真是醉了 以为死循环了 原来是循环套的太多了 出一组样例 500S+ 递归尽量减少嵌套循环 会死 我的复杂度34*14*13*12*11*10*9*8*7*6*5*4*3*2*1 提前脑子不好用啊!!!
特别注意以后回溯千万别忘记调用函数后还要把变量改回来

#include
   
     #include
    
      #include
     
       #include
      
        #include
       
         using namespace std; vector
        
          have; set
         
           ans; int ji = 0,kase = 0; bool zuhe(vector
          
            now) { int flagzong = 0; for(int i = 0; i < now.size(); i++) if(now[i] != 99) { flagzong = 1; break; } if(!flagzong) return true; //终于完事了 for(int i = 0; i < now.size(); i++) for(int j = 0; j < now.size(); j++) for(int k = 0; k < now.size(); k++) { if(i == j || i == k || j == k || now[i] == 99 || now[j] == 99 || now[k] == 99) continue; int a = now[i],b = now[j],c = now[k]; int flag = 0; if(a == b && a == c) //刻子 { vector
           
             now1(now); now1[i] =99; now1[j] =99; now1[k] =99; if(zuhe(now1)) return true; } else if((a >= 0 && a <= 8 && b >= 0 && b <= 8 && c >= 0 && c <= 8)||(a >= 9 && a <= 17 && b >= 9 && b <= 17 && c >= 9 && c <= 17)||(a >= 18 && a <= 26 && b >= 18 && b <= 26 && c >= 18 && c <= 26)) //顺子 { if(a + 1 == b && b + 1 == c) flag = 1; if(a + 1 == c && c + 1 == b) flag = 1; if(b + 1 == a && a + 1 == c) flag = 1; if(b + 1 == c && c + 1 == a) flag = 1; if(c + 1 == a && a + 1 == b) flag = 1; if(c + 1 == b && b + 1 == a) flag = 1; if(flag) { vector
            
              now1(now); now1[i] =99; now1[j] =99; now1[k] =99; if(zuhe(now1)) return true; } } } return false; } bool ting(vector
             
               now) //选择两个牌做将 { for(int i = 0; i < now.size(); i++) for(int j = 0; j < now.size(); j++) { if(i == j || now[i] != now[j]) continue; vector
              
                temp(now); temp[i] = 99; temp[j] = 99; if(zuhe(temp)) return true; } return false; } void solve() { for(int i = 0; i < 34; i++) { int countt = 0; for(int j = 0; j < have.size(); j++) if(have[j] == i) countt++; if(countt < 4) { vector
               
                 temp(have); temp.push_back(i); if(ting(temp)) ans.insert(i); } } } void build(string str) { if(str == "DONG") have.push_back(27); if(str == "NAN") have.push_back(28); if(str == "XI") have.push_back(29); if(str == "BEI") have.push_back(30); if(str == "ZHONG") have.push_back(31); if(str == "FA") have.push_back(32); if(str == "BAI") have.push_back(33); if(str[1] == 'T') have.push_back(str[0] - '0' - 1); if(str[1] == 'S') have.push_back(str[0] - '0' + 8); if(str[1] == 'W') have.push_back(str[0] - '0' + 17); } void print() { set
                
                 ::iterator it; if(ans.empty()) { printf(" Not ready\n"); return; } for(it = ans.begin(); it != ans.end(); it++) { printf(" "); if((*it) >= 0 && *it <= 8) printf("%dT",(*it) + 1); if((*it) >= 9 && *it <= 17) printf("%dS",(*it) - 8); if((*it) >= 18 && *it <=26) printf("%dW",(*it) - 17); if((*it) == 27) printf("DONG"); if((*it) == 28) printf("NAN"); if((*it) == 29) printf("XI"); if((*it) == 30) printf("BEI"); if((*it) == 31) printf("ZHONG"); if((*it) == 32) printf("FA"); if((*it) == 33) printf("BAI"); } printf("\n"); return; } int main() { string str; while(cin>>str && str != "0") { build(str); ji++; if(ji % 13 == 0) { solve(); printf("Case %d:",++kase); print(); ji = 0; have.clear(); ans.clear(); } } return 0; } 
                
               
              
             
            
           
          
         
        
       
      
     
    
   

以下是佳神的代码:

#include
   
     #include
    
      int mj[20], cnt[35]; const char* mahjong[]={"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"}; int getNum(char *str) { //将牌面转换为编号 for (int i = 0; i < 34; i++) { if (!strcmp(mahjong[i], str)) return i; } } int check2(int n) { for (int i = 0; i < 34; i++) { //刻子 if (cnt[i] >= 3) { if (n == 3) return 1; cnt[i] -= 3; if (check2(n + 1)) return 1; cnt[i] += 3; } } for (int i = 0; i <= 24; i++) { //顺子 if (i % 9 <= 6 && cnt[i] && cnt[i + 1] && cnt[i + 2]) { if (n == 3) return 1; cnt[i]--; cnt[i + 1]--; cnt[i + 2]--; if (check2(n + 1)) return 1; cnt[i]++; cnt[i + 1]++; cnt[i + 2]++; } } return 0; } int check() { for (int i = 0; i < 34; i++) { if (cnt[i] >= 2) {//将 cnt[i] -= 2; if (check2(0)) return 1; cnt[i] += 2; } } return 0; } int main() { char str[3]; int Case = 1; while (scanf("%s", str) == 1) { if (strcmp(str, "0") == 0) break; printf("Case %d:", Case++); mj[0] = getNum(str); for (int i = 1; i < 13; i++) { scanf("%s", str); mj[i] = getNum(str);//将牌面转化为编号 } int flag = 0; for (int i = 0; i < 34; i++) {//枚举34种可能和的情况 memset(cnt, 0, sizeof(cnt)); for (int j = 0; j < 13; j++) { cnt[mj[j]]++;//统计每张牌出现次数 } if (cnt[i] >= 4) continue;//已出现四次则不再考虑这张牌 cnt[i]++; if (check()) { flag = 1; printf(" %s", mahjong[i]); } } if (!flag) printf(" Not ready/n"); else printf("/n"); } return 0; } 
    
   
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇矩阵乘法 下一篇分拆数组技巧应用

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Redis on AWS:Elast (2025-12-27 04:19:30)
·在 Spring Boot 项目 (2025-12-27 04:19:27)
·使用华为开发者空间 (2025-12-27 04:19:24)
·Getting Started wit (2025-12-27 03:49:24)
·Ubuntu 上最好用的中 (2025-12-27 03:49:20)