解题报告:题目大意,给你n个球,要将这n个球从下到上按层次排列,要求同一个层次的的每一个分支的数量都必须相等,问有多少种排列的方法。
此题的一个DP题,假设现在有n个球,要将这n个球排列好,我们就必须将n个球的问题转化成小于n个球的子问题 ,我们可以很明显地观察到,对于每一种排列 的方法,它的最上面的那一层总是只有一个球,所以我们就可以这样出发,将这n个球先减掉一个球,还剩下n-1个球,然后就是下一层怎么排列 的问题了。由于现在还剩下n-1个球,那么我们现在要想的就是把这n-1个球应该怎么排列,很显然,我们可以在第二层只放一个球,也可以放两个球,3个,四个、、、、n-1,判断下面一层放i个球到底是否可行的方法就是判断这n-1个球能否被平均分成i份,因为当第二层放了i个球之后,每个球的下一层要放同样多的球,所以要求就是能将这n-1个球平均分成i份就可以了。
1 #include<cstdio> 2 #include<cstring> 3 const char feng[50][10]={"","DONG","NAN","XI","BEI","ZHONG","FA","BAI"}; 4 const char hua[50][3]={"T","S","W"}; 5 int mj[40],majiang[14]; 6 int judge(char *p) { 7 if(p[0]>='0'&&p[0]<='9') { 8 if(p[1]=='T') 9 return (p[0]-'0'-1); 10 else if(p[1]=='S') 11 return (8+p[0]-'0'); 12 else return (17+p[0]-'0'); 13 } 14 else { 15 for(int i=1;i<=7;++i) 16 if(!strcmp(feng[i],p)) 17 return (26+i); 18 } 19 } 20 bool find() { 21 for(int i=0;i<34;++i) { 22 if( mj[i] == 0 ) 23 continue; 24 if(mj[i]>=3) { 25 mj[i]-=3; 26 i=0; 27 continue; 28 } 29 else if(i%9<=6 && i <= 24 &&mj[i]>=1&&mj[i+1]>=1&&mj[i+2]>=1) { 30 mj[i]--; 31 mj[i+1]--; 32 mj[i+2]--; 33 i=0; 34 continue; 35 } 36 else return false; 37 } 38 return true; 39 } 40 bool check(int d) { 41 for(int i=0;i<34;++i) { 42 memset(mj,0,sizeof(mj)); 43 for(int j=0;j<13;++j) 44 mj[majiang[j]]++; 45 if(mj[d]>=4) 46 continue; 47 mj[d]++; 48 if(mj[i]>=2) { 49 mj[i]-=2; 50 if(find()) return true; 51 } 52 } 53 return false; 54 } 55 int main() { 56 char str[10]; 57 int Case=1; 58 while(scanf("%s",str)&&str[0]!='0') { 59 majiang[0]=judge(str); 60 int flag=0; 61 printf("Case %d:",Case++); 62 for(int i = 0; i<12;++i) { 63 scanf("%s",str); 64 majiang[i+1]=judge(str); 65 } 66 for(int i=0;i<34;++i) { 67 if(check(i)) { 68 flag=1; 69 if(i>=0&&i<=26) 70 printf(" %d%s",(i%9+1),hua[i/9]); 71 else printf(" %s",feng[i-26]); 72 } 73 } 74 if(!flag) 75 printf(" Not ready"); 76 printf(" "); 77 } 78 return 0; 79 }