斗地主 (NOIP2015 Day1 T3)
斗地主
思路 :读入时注意将A作为第14张牌,因为它可以连在K后,
总体思路为 先出炸弹和四带二 再出三带一 再把对牌和单牌出完 记录并更新Answer,后枚举顺子,并继续向下搜索。
注意:弄明白题意,题目描述不太清楚。。。。另外,我觉的牌的花色只是能用来区分大小王。另外在整顺子之前也可以用贪心来搞其他类似四带二,三带一等的牌
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int Max = 20; int T, N, Answer ; int card [Max]; int Count [Max]; void DFS (int X) { if (X > Answer ) return; int rest = 0; memset (Count, 0, sizeof (Count)); for (int i = 0; i <= 14; i++) Count [card[i]]++; for (; Count [4]; ) { Count [4]--; //炸弹 rest++; if (Count [2] >= 2) //判断能不能带2 Count [2] -= 2; else if (Count [1] >= 2) Count [1] -= 2; } for (; Count [3]; ) { Count [3]--; //三张牌 rest++; if (Count [2]) //能不能带一 Count [2]--; else if (Count [1]) Count [1]--; } if (card [0] && card [1] && Count [1] >= 2) //看看剩下的单牌有没有王炸 rest--; rest += Count [1] + Count [2]; Answer = min (rest + X, Answer ); for (int i = 3, j; i <= 14; ++i) //单顺子 { for (j = i; card [j] && j <= 14; ++j) { card [j]--; if (j - i + 1 >= 5) //如果剩下的牌多于五张 ,则向下搜索 DFS (X + 1); } for (; j > i; ) card [--j]++; } for (int i = 3, j; i <= 15; ++i) //双顺子 { for (j = i; card [j] >= 2 && j <= 14; ++j) { card [j] -= 2; if (j - i + 1 >= 3) DFS(X + 1); } for (; j > i; ) card [--j] += 2; } for (int i = 3, j; i <= 15; ++i) // 三顺子 { for (j = i; card [j] >= 3 && j <= 14; ++j) { card [j] -= 3; if (j - i + 1 >= 2) DFS (X + 1); } for (; j>i;) card [--j] += 3; } } int main() { cin >> T >> N; int A, B; while (T--) { memset (card, 0, sizeof (card)); Answer = N; for (int i = 1; i <= N; i++) { cin >> A >> B; if (A == 0) card [B - 1]++; //王 要分开存 ,因为他们不能组成对子 ,不能当对牌出 else if (A == 1) card [14]++; else card [A]++; } DFS (0); cout << Answer << endl; } return 0; }
myj 吊打我Orz,xxy 捆起来打我Orz,myl 文化课上天Orz, lrh 姿势水平敲高Orz, hkd 特别胖Orz%%%,cys 智商感人Orz,syl zz专业Orz,我没有学上, 我们未来一片光明