BZOJ1028 JSOI2007 麻将 枚举

题意:给定3*M+1张写有数字1到N的牌,求添加一个数字,使得所有的牌在删除两个数字相同的牌后,能够分成M组,其中每一组要么由相同的数字组成,要么由连续的数字组成。N≤400,M≤1000题解:暴力枚举加哪张牌,然后暴力枚举删哪两张牌,然后枚举判定是否合法。每次判定时先删除相同数字,后删除连续数字,至于为什么……我也不知道,反正我就这么WA了一次,举个例子,比如1 2 3 4的牌数分别是10 3 3 2,如果先把连续的数字删除就得到7 0 0 2不合法,但实际上如果我们先删除相同的数字,那么就有1 3 3 2->0 2 2 2->0 0 0 0合法

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int MAXN=400+2;
int N,M,C[MAXN],T[MAXN],Ans[MAXN];

bool Check(){
    bool Flag;
    for(int i=1;i<=N;i++)
        if(C[i]>1){
            Flag=1,C[i]-=2;

            for(int j=1;j<=N+2;j++) T[j]=C[j];
            for(int j=1;j<=N+2;j++){
                if(T[j]<0){
                    Flag=0;
                    break;
                }
                T[j]%=3,T[j+1]-=T[j],T[j+2]-=T[j];
            }

            C[i]+=2;
            if(Flag) return 1;
        }
    return 0;
}

int main(){
    scanf("%d %d",&N,&M);
    for(int i=1,t;i<=3*M+1;i++) scanf("%d",&t),C[t]++;

    for(int i=1;i<=N;i++){
        C[i]++;
        if(Check()) Ans[++Ans[0]]=i;
        C[i]--;
    }

    if(!Ans[0]) cout << "NO" << endl;
    else
        for(int i=1;i<=Ans[0];i++){
            cout << Ans[i];
            if(Ans[0]!=i) cout << " ";
        }

    return 0;
}
View Code

 

posted @ 2017-02-26 10:56  WDZRMPCBIT  阅读(183)  评论(0编辑  收藏  举报