描述
牛牛最近迷上了一种叫斗地主的扑克游戏。斗地主是一种使用黑桃、红心、梅花、 方片的A到K加上大小王的共54张牌来进行的扑克牌游戏。在斗地主中,牌的大小关系根据牌的数码表示如下:
3<4<5<6<7<8<9<10<J<Q<K<A<2〈小王〈大王,
而花色并不对牌的大小产生影响。每一局游戏中,一副手牌由n张牌组成。游戏者每次可以根据规 定的牌型行出牌,首先打光自己的手牌一方取得游戏的胜利。
现在,牛牛只想知道,对于自己的若干组手牌,分别最少需要多少次出牌可以将它 们打光。请你帮他解决这个问题。
需要注意的是,本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。 具体规则如下:
输入
输入文件名为landlords.in。
第一行包含用空格隔开的2个正整数T,n,表示手牌的组数以及每组手牌的张数。 接下来T组数据,每组数据n行,每行一个非负整数对^,^,表示一张牌,其中…表 示牌的数码,^表示牌的花色,中间用空格隔开。
特别的,我们用1来表示数码A,11表 示数码J,12表示数码Q,13表示数码K;黑桃、红心、梅花、方片分别用1-4来表示;小 王的表示方法为0 1,大王的表示方法为0 2。
输出
输出文件名为landlords.out。
共T行,每行一个整数,表示打光第i组手牌的最少次数。
样例1:
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
样例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 3
5 2
12 4
2 2
7 2
1 8
7 4
8 4
9 1
10 4
11 1
5 1
1 4
1 1
样例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 3
5 2
12 4
2 2
7 2
提示
样例1说明:
共有1组手牌,包含8张牌:方片7,方片8,黑桃9,方片10,黑桃J,黑桃5,方 片A以及黑桃A。可以通过打单顺子(方片7,方片8,黑桃9,方片10,黑桃J),单张 牌(黑桃5)以及对子牌(黑桃A以及方片A)在3次内打光。
如果直接暴力搜索能有30分
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int ans=23,leftttttttt; 6 int pai[30]; 7 void dfs(int s){ 8 //cout<<s<<endl; 9 if(s>=ans)return; 10 if(leftttttttt==0){ 11 ans=min(ans,s); 12 return; 13 } 14 if(pai[16]&&pai[17]){//火箭 15 pai[16]=0; 16 pai[17]=0; 17 leftttttttt-=2; 18 dfs(s+1); 19 leftttttttt+=2; 20 pai[17]=1; 21 pai[16]=1; 22 } 23 for(int i=3;i<=17;i++){//炸弹 24 if(pai[i]>=4){ 25 pai[i]-=4; 26 leftttttttt-=4; 27 dfs(s+1); 28 leftttttttt+=4; 29 pai[i]+=4; 30 } 31 } 32 for(int i=3;i<=17;i++){//单张牌 33 if(pai[i]){ 34 pai[i]--; 35 leftttttttt--; 36 dfs(s+1); 37 leftttttttt++; 38 pai[i]++; 39 } 40 } 41 for(int i=3;i<=17;i++){//对子牌 42 if(pai[i]>=2){ 43 pai[i]-=2; 44 leftttttttt-=2; 45 dfs(s+1); 46 leftttttttt+=2; 47 pai[i]+=2; 48 } 49 } 50 for(int i=3;i<=17;i++){//三张牌 51 if(pai[i]>=3){ 52 pai[i]-=3; 53 leftttttttt-=3; 54 dfs(s+1); 55 leftttttttt+=3; 56 pai[i]+=3; 57 } 58 } 59 for(int i=3;i<=17;i++){//三带一 60 if(pai[i]>=3){ 61 for(int j=3;j<=17;j++){ 62 if(j==i)continue; 63 if(!pai[j])continue; 64 pai[i]-=3; 65 pai[j]--; 66 leftttttttt-=4; 67 dfs(s+1); 68 leftttttttt+=4; 69 pai[j]++; 70 pai[i]+=3; 71 } 72 } 73 } 74 for(int i=3;i<=17;i++){//三带二 75 if(pai[i]>=3){ 76 for(int j=3;j<=17;j++){ 77 if(j==i)continue; 78 if(pai[j]<2)continue; 79 pai[i]-=3; 80 pai[j]-=2; 81 leftttttttt-=5; 82 dfs(s+1); 83 leftttttttt+=5; 84 pai[j]+=2; 85 pai[i]+=3; 86 } 87 } 88 } 89 for(int i=3;i<=17;i++){//四带二 90 if(pai[i]>=4){ 91 for(int j=3;j<=17;j++){ 92 if(i==j)continue; 93 if(pai[j]<2)continue; 94 pai[i]-=4; 95 pai[j]-=2; 96 leftttttttt-=6; 97 dfs(s+1); 98 leftttttttt+=6; 99 pai[j]+=2; 100 pai[i]+=4; 101 } 102 } 103 } 104 for(int i=3;i<=13;i++){//单顺子 105 for(int j=i+4;j<=17;j++){ 106 int flag=0; 107 for(int k=i;k<=j;k++){ 108 if(!pai[k]){ 109 flag=1; 110 break; 111 } 112 } 113 if(flag)continue; 114 for(int k=i;k<=j;k++){ 115 pai[k]--; 116 } 117 leftttttttt-=j-i+1; 118 dfs(s+1); 119 leftttttttt+=j-i+1; 120 for(int k=i;k<=j;k++){ 121 pai[k]++; 122 } 123 } 124 } 125 for(int i=3;i<=15;i++){//双顺子 126 for(int j=i+2;j<=17;j++){ 127 int flag=0; 128 for(int k=i;k<=j;k++){ 129 if(pai[k]<2){ 130 flag=1; 131 break; 132 } 133 } 134 if(flag)continue; 135 for(int k=i;k<=j;k++){ 136 pai[k]-=2; 137 } 138 leftttttttt-=(j-i+1)*2; 139 dfs(s+1); 140 leftttttttt+=(j-i+1)*2; 141 for(int k=i;k<=j;k++){ 142 pai[k]+=2; 143 } 144 } 145 } 146 for(int i=3;i<=16;i++){//三顺子 147 for(int j=i+1;j<=17;j++){ 148 int flag=0; 149 for(int k=i;k<=j;k++){ 150 if(pai[k]<3){ 151 flag=1; 152 break; 153 } 154 } 155 if(flag)continue; 156 for(int k=i;k<=j;k++){ 157 pai[k]-=3; 158 } 159 leftttttttt-=(j-i+1)*3; 160 dfs(s+1); 161 leftttttttt+=(j-i+1)*3; 162 for(int k=i;k<=j;k++){ 163 pai[k]+=3; 164 } 165 } 166 } 167 } 168 int main(){ 169 int T,n; 170 cin>>T>>n; 171 int a,b; 172 while(T--){ 173 memset(pai,0,sizeof pai); 174 leftttttttt=n; 175 for(int i=1;i<=n;i++){ 176 cin>>a>>b; 177 if(a==1)pai[14]++; 178 else if(a==2)pai[15]++; 179 else if(a==0){ 180 if(b==1)pai[16]++; 181 else pai[17]++; 182 } 183 else pai[a]++; 184 } 185 ans=23; 186 dfs(0); 187 // for(int i=3;i<=17;i++)cout<<pai[i]<<" "; 188 cout<<ans<<endl; 189 } 190 }