题目链接: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;
}
原文地址:http://blog.csdn.net/u010304217/article/details/38867661