这题就是一个简单的暴力,但考试的时候不知道脑子在想什么,什么都没打出来,也许是我想的太多了。。。
这道题对于不会打麻将的人来说还是有点难理解规则的,我没说过我会打麻将,这里是题目链接。
20分思路,利用深搜来寻找答案,我们先枚举每一张听牌,那么很显然,时间复杂度就是O(n),再用深搜来判断可否胡牌。首先,我们用t[x]t[x]来表示数值为x的牌出现了多少次。那么我们就从1到n枚举对子,再枚举刻子和顺子。那么深搜的时间复杂度约是O(2n2),合起来就是O(2n^3)O(2n3)。因为9<=n<=400,所以会超时。但是不能够同时枚举多个顺子。
100分思路:
还是先枚举听牌,然后再枚举对子,接着枚举多对刻子,最后再枚举顺子。
如果我们设e数组是当前的牌的状态,那么关键代码就是:
1 e[j]%=3; 2 e[j+1]-=e[j]; 3 e[j+2]-=e[j];
那么当e[j]<0时就说明这张牌不是听牌。
下面给一组数据用于对拍:
数据输入:
9 4
1 2 3 3 4 4 5 6 8 8 9 9 9
数据输出:
2 5
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cstdlib>
5 using namespace std;
6 int n,m;
7 bool flag=1;
8 const int maxn=1e6+10;
9 int t[maxn];
10 int e[maxn];
11 bool check()
12 {
13 for(int i=1;i<=n;i++)
14 {
15 if(t[i]>=2)
16 {
17 bool ju=0;
18 t[i]-=2;
19 for(int j=1;j<=n+2;j++)
20 {
21 e[j]=t[j];
22 }
23 for(int j=1;j<=n+2;j++)
24 {
25 if(e[j]<0)
26 {
27 ju=1;
28 break;
29 }
30 e[j]%=3;
31 e[j+1]-=e[j];
32 e[j+2]-=e[j];
33 }
34 t[i]+=2;
35 if(ju==0)
36 {
37
38 return 0;
39 }
40 }
41 }
42 return 1;
43 }
44 int main()
45 {
46 cin>>n>>m;
47 for(int i=1;i<=3*m+1;i++)
48 {
49 int x;
50 cin>>x;
51 t[x]++;
52 }
53 for(int i=1;i<=n;i++)
54 {
55 t[i]++;
56 memset(e,0,sizeof(e));
57 if(check()==0)
58 {
59 flag=0;
60 cout<<i<<" ";
61 }
62 t[i]--;
63 }
64 if(flag==1)
65 {
66 cout<<"NO";
67 }
68 return 0;
69 }
然后好心提供所有数据。。。
链接: https://pan.baidu.com/s/1aZVMqiRhYBqbMgofuzcLIw
提取码: f8ad