BZOJ[1028] [JSOI2007]麻将

首先,n比较小,可以枚举,那么我们就可以枚举到底插入哪一张牌,然后开始想的方法是直接按照一种贪心的策略来判断是否合法,但是总是没有办法覆盖到所有的情况所以可以在枚举到底是哪两张牌做对,然后就是保证剩下的牌能全部三个三个的打出就行了;

具体办法就是从1到n,每一个数都%3,然后用后两个数减去他的模数,以为一个牌如果自己三个三个的没有办法出完,那么一定要有顺子,然后从前往后推过去就好,至于为什么%3,那是因为出333 444 555 和345 345 345 的效果是一样的;

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 # define maxn 1010
 8 using namespace std;
 9 int n,m;
10 int Num[maxn];
11 int cun[maxn];
12 bool check(int x){
13     int mn;
14     for(int i=1;i<=n;i++){
15         memcpy(cun,Num,sizeof(cun)); cun[x]++;
16         if(cun[i]<2) continue; cun[i]-=2;
17         bool ok=1;
18         for(int j=1;j<=n;j++){
19             cun[j]%=3; int tt=cun[j];
20             for(int k=j;k<=j+2;k++) {
21                 cun[k]-=tt;
22                 if(cun[k]<0){ok=0; break;}
23             }
24         }
25         if(ok) return 1;
26     }
27     return 0;
28 }
29 int ans[maxn];
30 int main(){
31     // freopen("a.in","r",stdin);
32     scanf("%d%d",&n,&m); int x;
33     for(int i=1;i<=3*m+1;i++){
34         scanf("%d",&x); Num[x]++;
35     }
36     for(int i=1;i<=n;i++){
37         if(check(i)){
38             ans[++ans[0]]=i;
39         }
40     }
41     if(ans[0]==0){
42         cout<<"NO"<<endl; return 0;
43     }
44     for(int i=1;i<ans[0];i++){
45         cout<<ans[i]<<" ";
46     }
47     cout<<ans[ans[0]]<<endl;
48     return 0;
49 }
View Code

 

posted @ 2017-10-11 21:45  Nawox  阅读(150)  评论(0编辑  收藏  举报