大名鼎鼎的NOIP2015D1T3
题意:
由于一些众所周知的原因,没有完整题面……
给你一副斗地主的手牌(牌数<=23),问最少要几次能出完;
包含双王,没有癞子,连对要三连对以上,可以直接出三张同点数的牌(三对),可以出连着的三对,也可以三带一,三带二,但不能出飞机,可以四张带一对或两张单牌。
题解:
神题啊……orz……虽然写起来并不麻烦,但是当年这个神之题面真是雷倒了无数选手……
提前来做的原因是今天xfz出了一道毒瘤题(密码:yxqak)……是这题的弱化版(其实是道水题啦),本蒟蒻看到题面就吓傻了不敢打,改完题来膜一下原题……
首先注意到花色和点数大小是没用的(王也可以被带着出),且出牌时除非出顺子(连对,连三对),否则出牌的顺序是不会影响到最后答案的;
并且牌数很少(毕竟是斗地主嘛……),最多只会有四个顺子,所以可以直接暴力dfs把所有顺子找出来,枚举怎么出每一个顺子,然后再贪心处理当前的出牌情况;
很容易想到把牌组合起来出越多越好,贪心优先四带二,三带二,三带一,剩余的炸弹,三对,对子和单张直接出掉;
于是就……做完了。
ps:然而实际上由于本题数据太小,爆搜可以轻松通过
(听说欢乐斗地主上100w豆即可一秒切掉此题)
代码:
1 #include2 #include 52 for(int l=i;l<=k;l++){ 53 num[l]-=3; 54 } 55 dfs(nw+1); 56 for(int l=i;l<=k;l++){ 57 num[l]+=3; 58 } 59 } 60 } 61 } 62 for(int i=3,j;i<=14;i++){ 63 j=i; 64 while(num[j]>=2&&j<=14)j++; 65 if(j-i>=3){ 66 for(int k=i+2;k3 #include 4 #include 5 #include 6 #include 7 #define inf 2147483647 8 #define eps 1e-9 9 using namespace std; 10 typedef long long ll; 11 int t,n,x,y,ans,num[17],tot[5]; 12 int gao(){ 13 int ret=0; 14 memset(tot,0,sizeof(tot)); 15 for(int i=3;i<=16;i++){ 16 tot[num[i]]++; 17 } 18 while(tot[4]&&tot[2]>=2){ 19 tot[4]--; 20 tot[2]-=2; 21 ret++; 22 } 23 while(tot[4]&&tot[1]>=2){ 24 tot[4]--; 25 tot[1]-=2; 26 ret++; 27 } 28 while(tot[4]&&tot[2]){ 29 tot[4]--; 30 tot[2]--; 31 } 32 while(tot[3]&&tot[2]){ 33 tot[3]--; 34 tot[2]--; 35 ret++; 36 } 37 while(tot[3]&&tot[1]){ 38 tot[3]--; 39 tot[1]--; 40 ret++; 41 } 42 return ret+tot[1]+tot[2]+tot[3]+tot[4]; 43 } 44 void dfs(int nw){ 45 if(nw>=ans)return; 46 ans=min(ans,nw+gao()); 47 for(int i=3,j;i<=14;i++){ 48 j=i; 49 while(num[j]>=3&&j<=14)j++; 50 if(j-i>=2){ 51 for(int k=i+1;k ){ ){ 67 for(int l=i;l<=k;l++){ 68 num[l]-=2; 69 } 70 dfs(nw+1); 71 for(int l=i;l<=k;l++){ 72 num[l]+=2; 73 } 74 } 75 } 76 } 77 for(int i=3,j;i<=14;i++){ 78 j=i; 79 while(num[j]&&j<=14)j++; 80 if(j-i>=5){ 81 for(int k=i+4;k ){ 82 for(int l=i;l<=k;l++){ 83 num[l]--; 84 } 85 dfs(nw+1); 86 for(int l=i;l<=k;l++){ 87 num[l]++; 88 } 89 } 90 } 91 } 92 } 93 int main(){ 94 scanf("%d%d",&t,&n); 95 while(t--){ 96 ans=inf; 97 memset(num,0,sizeof(num)); 98 for(int i=1;i<=n;i++){ 99 scanf("%d%d",&x,&y); 100 if(!x)x=16; 101 if(x==1)x=14; 102 if(x==2)x=15; 103 num[x]++; 104 } 105 dfs(0); 106 printf("%d\n",ans); 107 } 108 return 0; 109 }