【NOIP2015 DAY1 T3 】斗地主(landlords)
2016-08-06 10:54
441 查看
题目描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。
具体规则如下:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define Maxs 2000010 int n,maxx; int sum[20],k[20],f[Maxs]; int mymin(int x,int y) {return x<y?x:y;} void init() { int a,b; for(int i=0;i<=13;i++) sum[i]=0; for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); sum[a]++; } k[0]=1; for(int i=1;i<=13;i++) k[i]=k[i-1]*(sum[i-1]+1); maxx=k[13]*(sum[13]+1)-1; memset(f,63,sizeof(f)); f[0]=0; } int ffind(int s) { if(f[s]<100) return f[s]; int now[20]; int ss=s; for(int i=13;i>=0;i--) if(sum[i]) { if(i!=0) { now[i]=ss/k[i]; if(ss) ss%=k[i]; } else now[i]=ss; } else now[i]=0; //-dan-shunzi for(int i=3;i<=9;i++) { bool ok=1;ss=s; for(int j=i;j<=i+4;j++) { if(now[j]==0) {ok=0;break;} ss-=k[j]; } if(!ok) continue; f[s]=mymin(f[s],ffind(ss)+1); for(int j=i+5;j<=13;j++) { if(now[j]>=1) { ss-=k[j]; f[s]=mymin(f[s],ffind(ss)+1); } else {ok=0;break;} } if(now[1]&&ok) { ss-=k[1]; f[s]=mymin(f[s],ffind(ss)+1); } } if(now[1]&&now[13]&&now[12]&&now[11]&&now[10]) f[s]=mymin(f[s],ffind(s-k[1]-k[13]-k[12]-k[11]-k[10])+1); //shuang shun for(int i=3;i<=11;i++) { bool ok=1;ss=s; for(int j=i;j<=i+2;j++) { if(now[j]<2) {ok=0;break;} ss-=k[j]*2; } if(!ok) continue; f[s]=mymin(f[s],ffind(ss)+1); for(int j=i+3;j<=13;j++) { if(now[j]>=2) { ss-=2*k[j]; f[s]=mymin(f[s],ffind(ss)+1); } else {ok=0;break;} } if(ok&&now[1]>=2) { ss-=2*k[1]; f[s]=mymin(f[s],ffind(ss)+1); } } if(now[1]>=2&&now[13]>=2&&now[12]>=2) f[s]=mymin(f[s],ffind(s-2*k[1]-2*k[13]-2*k[12])+1); //san shun for(int i=3;i<=12;i++) { if(now[i]<3||now[i+1]<3) continue; ss=s-k[i]*3-k[i+1]*3; f[s]=mymin(f[s],ffind(ss)+1); bool ok=1; for(int j=i+2;j<=13;j++) { if(now[j]>=3) { ss-=3*k[j]; f[s]=mymin(f[s],ffind(ss)+1); } else {ok=0;break;} } if(now[1]>=3&&ok) { ss-=3*k[1]; f[s]=mymin(f[s],ffind(ss)+1); } } if(now[1]>=3&&now[13]>=3) f[s]=mymin(f[s],ffind(s-3*k[1]-3*k[13])+1); //4 dai 2 for(int i=1;i<=13;i++) if(now[i]==4) { ss=s-k[i]*4; f[s]=mymin(f[s],ffind(ss)+1); for(int j=0;j<=13;j++) if(i!=j&&now[j]) { if(now[j]>=2) f[s]=mymin(f[s],ffind(ss-2*k[j])+1); for(int l=j+1;l<=13;l++) if(l!=i&&now[l]) { if(now[j]>=2&&now[l]>=2&&j!=0) f[s]=mymin(f[s],ffind(ss-2*k[j]-2*k[l])+1); f[s]=mymin(f[s],ffind(ss-k[j]-k[l])+1); } } } //san dai x for(int i=1;i<=13;i++) if(now[i]>=3) { ss=s-k[i]*3; f[s]=mymin(f[s],ffind(ss)+1); for(int j=0;j<=13;j++) if(now[j]>=1&&i!=j) f[s]=mymin(f[s],ffind(ss-k[j])+1); for(int j=1;j<=13;j++) if(now[j]>=2&&i!=j) f[s]=mymin(f[s],ffind(ss-2*k[j])+1); } for(int i=0;i<=13;i++) if(now[i]>=1) f[s]=mymin(f[s],ffind(s-k[i])+1); for(int i=0;i<=13;i++) if(now[i]>=2) f[s]=mymin(f[s],ffind(s-2*k[i])+1); return f[s]; } int main() { int T; scanf("%d%d",&T,&n); while(T--) { init(); ffind(maxx); printf("%d\n",f[maxx]); } return 0; }
landlords
2016-08-06 10:57:25
相关文章推荐
- Noip2015 Day1 T3 斗地主(Dfs+Dp优化)
- 斗地主 (NOIP2015 Day1 T3)
- C++——NOIP2015提高组day1 t3——斗地主
- 洛谷P2668 斗地主==codevs 4610 斗地主[NOIP 2015 day1 T3]
- NOIP 2015 Day T3 landlords 斗地主
- NOIP 2015 D1 T3 斗地主(特详细讲解)
- NOIP2015 Day 1 T3 斗地主
- NOIP 2015[D1 T3]斗地主(30分的特判)
- 【jzoj4325】【NOIP2015提高组Day1】【斗地主】
- JZOJsenior4325、luoguP2668.【NOIP2015提高组Day1】斗地主
- 【NOIP2015提高组Day1】斗地主
- noip2015 day1 斗地主
- 4325. 【NOIP2015提高组Day1】斗地主
- NOIP2015复赛提高组day1(A:神奇的幻方 B:信息传递 C:斗地主)
- NOIP 2015 [D1 T3]斗地主
- NOIP 2015 提高组 Day1 斗地主
- [noip2015]斗地主(dfs+贪心)
- NOIP2015 斗地主 解题报告(搜索)
- 【BZOJ4325】NOIP2015 斗地主 搜索+贪心
- 【NOIP2015提高组Day1】 神奇的幻方