1. 程式人生 > >BZOJ.1028.[JSOI2007]麻將(貪心)

BZOJ.1028.[JSOI2007]麻將(貪心)

etc jsoi2007 TP fin line HP 處理 AI register

題目鏈接

枚舉對子,枚舉每張牌,先出完它的刻子,剩下的出順子。\(O(n^3)\).
不是這樣 -> 出完所有刻子,最後出順子。(日常zz)
優先仨相同的,然後順子,有一次且一定要用一次機會補順子的空位,即把刻子換成對子。這樣好像是\(O(n^2)\).
不寫\(O(n^2)\)的了,特判之類大概非常麻煩。。

//828kb 396ms
#include <cstdio>
#include <cctype>
#include <cstring>
#define gc() getchar()
const int N=407;

int n,m,tot,tmp[N],num[N],Ans[N];

inline
int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } bool Check() { for(int i=1; i<=n+2; ++i)//處理完前面的 才處理這張出刻子! if((num[i]%=3)>0) num[i+1]-=num[i], num[i+2]-=num[i], num[i]=0;//直接給減掉就行啊,判什麽 else
if(num[i]<0) return 0; return 1; } int main() { n=read(),m=read(),tot=3*m+1; for(int i=1; i<=tot; ++i) ++tmp[read()]; int cnt=0; for(int i=1; i<=n; ++i) { ++tmp[i]; for(int j=1; j<=n; ++j) if(tmp[j]>=2) { tmp[j]-=2
, memcpy(num,tmp,sizeof num), tmp[j]+=2; if(Check()) {Ans[++cnt]=i; break;} } --tmp[i]; } if(cnt) for(int i=1; i<=cnt; ++i) printf("%d ",Ans[i]); else puts("NO"); return 0; }

BZOJ.1028.[JSOI2007]麻將(貪心)