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; }