[NOIP2015]斗地主
2106. [NOIP2015] 斗地主
★★★☆ 输入文件:landlords.in
输出文件:landlords.out
简单对比
时间限制:2 s 内存限制:1025 MB
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规定的牌型进行出牌,首先打光自己的手牌一方取得游戏的胜利。
现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。
具体规则如下:
【输入格式】
第一行包含用空格隔开的2个正整数Tn,表示手牌的组数以及每组手牌的张数。
接下来T组数据,每组数据n行,每行一个非负整数对aibi表示一张牌,其中ai示牌的数码,bi表示牌的花色,中间用空格隔开。特别的,我们用1来表示数码A,11表示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小王的表示方法为01,大王的表示方法为02。
【输出格式】
共T行,每行一个整数,表示打光第i手牌的最少次数。
【样例输入1】
1 8 7 4 8 4 9 1 10 4 11 1 5 1 1 4 1 1
【样例输出1】
3
【样例输入2】
1 17 12 3 4 3 2 3 5 4 10 2 3 3 12 2 0 1 1 3 10 1 6 2 12 1 11 3 5 2 12 4 2 2 7 2
【样例输出2】
6
【提示】
样例1说明
共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。
对于不同的测试点, 我们约定手牌组数T与张数n的规模如下:
数据保证:所有的手牌都是随机生成的。
恩,这一定是一个伪的斗地主。我们看题目描述:发现确实没什么好的方法,而且数据范围又比较小,肯定是DFS无疑了,(但是为什么内存辣么大,吓坏我了( ⊙ o ⊙ )!)
这道题就没啦,因为dfs的层数会很多,所以一定要剪枝,减的越早越好!
(听说那些大佬们都拿数组传参打的,但是一个没有回溯的dfs不是一个好的dfs!);
附代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=14; 7 void dfs(int,int); 8 int read(){ 9 int sum=0;char ch=getchar(); 10 while(ch<'0'||ch>'9') ch=getchar(); 11 while(ch>='0'&&ch<='9') {sum=sum*10+ch-'0';ch=getchar();} 12 return sum; 13 } 14 inline int min(int x,int y){return x<y?x:y;} 15 int T,n,x,y; 16 int a[20],ans; 17 void three(int cnt,int sum){ 18 for(int i=3;i<=N-1;++i){ 19 if(a[i]>=3&&a[i+1]>=3){ 20 a[i]-=3;int j; 21 for(j=i+1;j;++j){ 22 if(a[j]>=3){ 23 a[j]-=3; 24 dfs(cnt+1,sum+3*(j-i+1)); 25 } 26 else 27 break; 28 } 29 for(j=j-1;j>i;j--){ 30 // dfs(cnt+1,sum+3*(j-i+1)); 31 a[j]+=3; 32 } 33 a[i]+=3; 34 } 35 } 36 } 37 void two(int cnt,int sum){ 38 for(int i=3;i<=N-2;++i){ 39 if(a[i]>=2&&a[i+1]>=2&&a[i+2]>=2){ 40 a[i]-=2;a[i+1]-=2;int j; 41 for(j=i+2;j;++j){ 42 if(a[j]>=2){ 43 a[j]-=2; 44 dfs(cnt+1,sum+2*(j-i+1)); 45 } 46 else 47 break; 48 } 49 for(j=j-1;j>=i+2;j--){ 50 a[j]+=2; 51 } 52 a[i]+=2;a[i+1]+=2; 53 } 54 } 55 } 56 void one(int cnt,int sum){ 57 for(int i=3;i<=N-4;++i){ 58 if(a[i]&&a[i+1]&&a[i+2]&&a[i+3]&&a[i+4]){ 59 a[i]--;a[i+1]--;a[i+2]--;a[i+3]--;int j; 60 for(j=i+4;;++j){ 61 if(a[j]){ 62 a[j]--; 63 dfs(cnt+1,sum+j-i+1); 64 } 65 else 66 break; 67 } 68 for(j=j-1;j>=i+4;j--){ 69 //dfs(cnt+1,sum+j-i+1); 70 a[j]++; 71 } 72 a[i]++;a[i+1]++;a[i+2]++;a[i+3]++; 73 } 74 } 75 } 76 void four_two(int cnt,int sum){ 77 for(int i=2;i<=N;++i) 78 if(a[i]==4){ 79 a[i]=0; 80 for(int j=0;j<=N;++j) 81 for(int u=j+1;u<=N;++u){ 82 if(a[j]==2&&a[u]==2){ 83 a[j]=0;a[u]=0; 84 dfs(cnt+1,sum+8); 85 a[j]=2;a[u]=2; 86 } 87 } 88 a[i]=4; 89 } 90 } 91 void four_twos(int cnt,int sum){ 92 for(int i=1;i<=N;++i) 93 if(a[i]==4){ 94 a[i]=0; 95 for(int j=0;j<=N;++j) 96 for(int u=j+1;u<=N;++u){ 97 if(a[j]==1&&a[u]==1){ 98 a[j]=0;a[u]=0; 99 dfs(cnt+1,sum+6); 100 a[j]=1;a[u]=1; 101 } 102 } 103 a[i]=4; 104 } 105 } 106 void three_two(int cnt,int sum){ 107 for(int i=1;i<=N;++i) 108 if(a[i]==3){ 109 a[i]=0; 110 for(int j=1;j<=N;++j) 111 if(a[j]==2){ 112 a[j]=0; 113 dfs(cnt+1,sum+5); 114 a[j]=2; 115 } 116 a[i]=3; 117 } 118 } 119 void three_one(int cnt,int sum){ 120 for(int i=1;i<=N;++i) 121 if(a[i]==3){ 122 a[i]=0; 123 for(int j=1;j<=N;++j) 124 if(a[j]){ 125 a[j]--; 126 dfs(cnt+1,sum+4); 127 a[j]++; 128 } 129 a[i]=3; 130 } 131 } 132 void third(int cnt,int sum){ 133 for(int i=1;i<=N;++i) 134 if(a[i]==3){ 135 a[i]=0; 136 dfs(cnt+1,sum+3); 137 a[i]=3; 138 } 139 } 140 void second(int cnt,int sum){ 141 for(int i=1;i<=N;++i) 142 if(a[i]==2){ 143 a[i]-=2; 144 dfs(cnt+1,sum+2); 145 a[i]+=2; 146 } 147 } 148 void dfs(int cnt,int sum){ 149 int pp=n-sum; 150 if(cnt>=ans) return; 151 if(pp>=6) three(cnt,sum); 152 if(pp>=6) two(cnt,sum); 153 if(pp>=5) one(cnt,sum); 154 if(pp>=8) four_two(cnt,sum); 155 if(pp>=6) four_twos(cnt,sum); 156 if(pp>=5) three_two(cnt,sum); 157 if(pp>=4) three_one(cnt,sum); 158 if(pp>=3) third(cnt,sum); 159 int zz=sum; 160 for(int i=1;i<=N;++i) 161 if(a[i]==2) 162 zz++; 163 ans=min(ans,cnt+n-zz); 164 165 } 166 int main(){ 167 freopen("landlords.in","r",stdin); 168 freopen("landlords.out","w",stdout); 169 T=read();n=read(); 170 while(T--){ 171 ans=0x7fffffff; 172 memset(a,0,sizeof(a)); 173 for(int i=1;i<=n;++i){ 174 x=read();y=read(); 175 if(x==1) a[14]++; 176 else if(!x) a[1]++; 177 else a[x]++; 178 } 179 dfs(0,0); 180 printf("%d\n",ans); 181 } 182 return 0; 183 }