单纯的暴搜似乎还是很好写的,然而过不了。出完顺子之后答案是可以dp出来的,于是大力搜然后大力dp就好了。
dp时强行讨论完了几乎所有拆牌情况,理性愉悦一发。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int T,n,cnt[20],f[24][13][9][7][3],ans;//1:2 2~12:3~K 13:A 14 15:ghost void dfs(int k,int step); void threestraight(int k,int step) { for (int i=2;i<=12;i++) if (cnt[i]>=3&&cnt[i+1]>=3) { cnt[i]-=3,cnt[i+1]-=3;dfs(k-6,step+1); int t=i+1;while (cnt[t+1]>=3) t++,cnt[t]-=3,dfs(k-(t-i+1)*3,step+1); while (t>=i) cnt[t]+=3,t--; } } void twostraight(int k,int step) { for (int i=2;i<=11;i++) if (cnt[i]>=2&&cnt[i+1]>=2&&cnt[i+2]>=2) { cnt[i]-=2,cnt[i+1]-=2,cnt[i+2]-=2;dfs(k-6,step+1); int t=i+2;while (cnt[t+1]>=2) t++,cnt[t]-=2,dfs(k-((t-i+1)<<1),step+1); while (t>=i) cnt[t]+=2,t--; } } void onestraight(int k,int step) { for (int i=2;i<=9;i++) if (cnt[i]&&cnt[i+1]&&cnt[i+2]&&cnt[i+3]&&cnt[i+4]) { cnt[i]--,cnt[i+1]--,cnt[i+2]--,cnt[i+3]--,cnt[i+4]--;dfs(k-5,step+1); int t=i+4;while (t<13&&cnt[t+1]) t++,cnt[t]--,dfs(k-(t-i+1),step+1); while (t>=i) cnt[t]++,t--; } } void dfs(int k,int step) { int t[6]={0}; for (int i=1;i<=13;i++) if (cnt[i]) t[cnt[i]]++; t[5]=cnt[14]+cnt[15]; ans=min(ans,step+f[t[1]][t[2]][t[3]][t[4]][t[5]]); if (step+(k>0)>=ans) return; if (k==0) return; threestraight(k,step); twostraight(k,step); onestraight(k,step); } inline void update(int &x,int y){x=min(x,y);} void dp() { memset(f,42,sizeof(f)); f[0][0][0][0][0]=0; for (int i=1;i<=n;i++) for (int x=0;x<=i;x++) for (int y=0;y*2<=i-x;y++) for (int z=0;z*3<=i-x-y*2;z++) for (int t=0;t*4<=i-x-y*2-z*3;t++) for (int g=0;g<=min(2,i-x-y*2-z*3-t*4);g++) { if (x) update(f[x][y][z][t][g],f[x-1][y][z][t][g]+1); if (y) update(f[x][y][z][t][g],f[x][y-1][z][t][g]+1); if (y) update(f[x][y][z][t][g],f[x+1][y-1][z][t][g]+1); if (z) update(f[x][y][z][t][g],f[x][y][z-1][t][g]+1); if (z) update(f[x][y][z][t][g],f[x][y+1][z-1][t][g]+1); if (z) update(f[x][y][z][t][g],f[x+1][y][z-1][t][g]+1); if (t) update(f[x][y][z][t][g],f[x][y][z][t-1][g]+1); if (t) update(f[x][y][z][t][g],f[x][y][z+1][t-1][g]+1); if (t) update(f[x][y][z][t][g],f[x][y+1][z][t-1][g]+1); if (t) update(f[x][y][z][t][g],f[x+1][y][z][t-1][g]+1); if (g) update(f[x][y][z][t][g],f[x][y][z][t][g-1]+1); if (g==2) update(f[x][y][z][t][g],f[x][y][z][t][g-2]+1); //part 1 only one if (z&&x) update(f[x][y][z][t][g],f[x-1][y][z-1][t][g]+1); if (z&&y) update(f[x][y][z][t][g],f[x+1][y-1][z-1][t][g]+1); if (z>=2) update(f[x][y][z][t][g],f[x][y+1][z-2][t][g]+1); if (z&&g) update(f[x][y][z][t][g],f[x][y][z-1][t][g-1]+1); if (t&&y) update(f[x][y][z][t][g],f[x+2][y-1][z][t-1][g]+1); if (t>=2) update(f[x][y][z][t][g],f[x+1][y][z+1][t-2][g]+1); if (t&&g) update(f[x][y][z][t][g],f[x][y][z][t-1][g-1]+1); //part 2 three with one if (z&&y) update(f[x][y][z][t][g],f[x][y-1][z-1][t][g]+1); if (z>=2) update(f[x][y][z][t][g],f[x+1][y][z-2][t][g]+1); if (z&&t) update(f[x][y][z][t][g],f[x][y+1][z-1][t-1][g]+1); if (t&&y) update(f[x][y][z][t][g],f[x+1][y-1][z][t-1][g]+1); if (t&&z) update(f[x][y][z][t][g],f[x+2][t][z-1][t-1][g]+1); if (t>=2) update(f[x][t][z][t][g],f[x+1][y+1][z][t-2][g]+1); //part 3 three with two if (t) { if (x>=2) update(f[x][y][z][t][g],f[x-2][y][z][t-1][g]+1); if (x&&g) update(f[x][y][z][t][g],f[x-1][y][z][t-1][g-1]+1); if (y) update(f[x][y][z][t][g],f[x][y-1][z][t-1][g]+1); if (y>=2) update(f[x][y][z][t][g],f[x+2][y-2][z][t-1][g]+1); if (y&&g) update(f[x][y][z][t][g],f[x+1][y-1][z][t-1][g-1]+1); if (z) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1); if (z&&x) update(f[x][y][z][t][g],f[x-1][y+1][z-1][t-1][g]+1); if (z&&y) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1); if (z>=2) update(f[x][y][z][t][g],f[x][y+1][z-2][t-1][g]+1); if (z&&g) update(f[x][y][z][t][g],f[x][y+1][z-1][t-1][g-1]+1); if (t>=2) update(f[x][y][z][t][g],f[x][y+1][z][t-2][g]+1); if (t>=3) update(f[x][y][z][t][g],f[x][y][z+2][t-3][g]+1); if (t>=2&&x) update(f[x][y][z][t][g],f[x-1][y][z+1][t-2][g]+1); if (t>=2&&y) update(f[x][y][z][t][g],f[x+1][y-1][z+1][t-2][g]+1); if (t>=2&&z) update(f[x][y][z][t][g],f[x][y+1][z][t-2][g]+1); if (t>=2&&g) update(f[x][y][z][t][g],f[x][y][z+1][t-2][g-1]+1); if (g>=2) update(f[x][y][z][t][g],f[x][y][z][t-1][g-2]+1); //part 4 four with one if (y>=2) update(f[x][y][z][t][g],f[x][y-2][z][t-1][g]+1); if (z>=2) update(f[x][y][z][t][g],f[x+2][y][z-2][t-1][g]+1); if (y&&z) update(f[x][y][z][t][g],f[x+1][y][z-1][t-1][g]+1); if (t>=2&&z) update(f[x][y][z][t][g],f[x+1][y+1][z-1][t-2][g]+1); if (t>=2) update(f[x][y][z][t][g],f[x][y][z][t-2][g]+1); if (t>=3) update(f[x][y][z][t][g],f[x][y+2][z][t-3][g]+1); //part 5 four with two } } } int main() { #ifndef ONLINE_JUDGE freopen("2540.in","r",stdin); freopen("2540.out","w",stdout); const char LL[]="%I64d "; #else const char LL[]="%lld "; #endif T=read(),n=read(); dp(); while (T--) { ans=n;memset(cnt,0,sizeof(cnt)); for (int i=1;i<=n;i++) { int x=read(),y=read(); if (x==0) cnt[y+13]++; else if (x==2) cnt[1]++; else if (x==1) cnt[13]++; else cnt[x-1]++; } dfs(n,0); cout<<ans<<endl; } return 0; }