题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3669
题目大意:就是给你一副牌,问你胡牌的方式有几种,并输出方式。。。。。
思路:因为一副牌的数量不多,所以可以直接枚举每一张牌,判断加上这张牌后能否胡牌。。。
code:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> using namespace std; struct node { int num; char kind; }s[1000]; char str[100]; int a[4][15]; int ta[4][15]; int len,cnt; int find(int num) { int i,j; if(num==0) return 1; for(i=0;i<4;i++) //判断三个为一组的情况 { for(j=1;j<=9;j++) { if(a[i][j]<3) continue; a[i][j]-=3; if(find(num-1)) return 1; a[i][j]+=3; //注意这儿的回溯 } } for(i=0;i<3;i++) //判断连牌的情况,并且连牌只可能前三类牌中出现 { for(j=1;j<=7;j++) { if(a[i][j]&&a[i][j+1]&&a[i][j+2]) { a[i][j]--; a[i][j+1]--; a[i][j+2]--; if(find(num-1)) { return 1; } a[i][j]++; //回溯 a[i][j+1]++; a[i][j+2]++; } } } return 0; } int solve() { int i,j; for(i=0;i<4;i++) { for(j=1;j<=9;j++) { if(a[i][j]<2) continue; if(i==3&&j<=7) { a[i][j]-=2; if(find(4)) return 1; a[i][j]+=2; } else if(i<3&&j<=9) { a[i][j]-=2; if(find(4)) return 1; a[i][j]+=2; } } } return 0; } int main() { int i,j,k; while(scanf("%s",str)!=EOF) { cnt=0; memset(a,0,sizeof(a)); for(i=0;i<26;i+=2) //记录每类牌的数量 { if(str[i+1]=='m') { a[0][str[i]-'0']++; } else if(str[i+1]=='p') { a[1][str[i]-'0']++; } else if(str[i+1]=='s') { a[2][str[i]-'0']++; } else if(str[i+1]=='z') { a[3][str[i]-'0']++; } } char kind[5]="mpsz"; for(i=1;i<=27+7;i++) //枚举每张牌表并判断 { int id=(i-1)/9; int no=i%9; if(no==0) { no=9; } memcpy(ta,a,sizeof(a)); if(id<4&&a[id][no]<4) { a[id][no]++; } else { continue; } if(solve()) //如果能胡牌,则记录下来 { s[cnt].num=no; s[cnt++].kind=kind[id]; } memcpy(a,ta,sizeof(ta)); } if(cnt==0) { printf("0\n"); } else { printf("%d ",cnt); for(i=0;i<cnt;i++) { printf("%d%c",s[i].num,s[i].kind); } printf("\n"); } } return 0; }
时间: 2024-10-07 19:00:49