【NOIP2015】斗地主

4610 斗地主
时间限制: 1 s
空间限制: 256000 KB
题目等级 : 大师 Master
题解
题目描述 Description
牛牛最近迷上了一种叫斗地主的扑克游戏。 斗地主是一种使用黑桃、红心、梅花、方片的 A 到 K 加上大小王的共 54 张牌来进行的扑克牌游戏。
在斗地主中, 牌的大小关系根据牌的数码表示如下: 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K < A < 2 < 小王 < 大王, 而花色并不
对牌的大小产生影响。 每一局游戏中,一副手牌由 n 张牌组成。游戏者每次可以根据规
定的牌型进行出牌, 首先打光自己的手牌一方取得游戏的胜利。
现在,牛牛只想知道,对于自己的若干组手牌, 分别最少需要多少次出牌可以将它
们打光。 请你帮他解决这个问题。
需要注意的是, 本题中游戏者每次可以出手的牌型与一般的斗地主相似而略有不同。
具体规则如下:

输入描述 Input Description
输入文件名为 landlords.in。
第一行包含用空格隔开的 2 个正整数T,n,表示手牌的组数以及每组手牌的张数。
接下来T组数据,每组数据n行, 每行一个非负整数ai,bi,对表示一张牌, 其中ai表
示牌的数码,bi表示牌的花色,中间用空格隔开。 特别的, 我们用1 来表示数码 A, 11 表
示数码 J, 12 表示数码 Q, 13 表示数码 K;黑桃、红心、梅花、方片分别用 1-4 来表示; 小
王的表示方法为 0 1, 大王的表示方法为 0 2。

输出描述 Output Description
输出文件名为 landlords.out。
共 T 行,每行一个整数,表示打光第i组手牌的最少次数。

样例输入 Sample Input
输入样例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 1
11 3

5 2
12 4
2 2
7 2

样例输出 Sample Output
输出样例1

3
—————

输出样例2

6

首先,花色没用
其次,牌的顺序与答案无关

搜索,找到暴力先出三带一四带一们
再开始找

#include 
#include 
#include 
#include 
#include 
#include 
#define ll long long
using namespace std;
const int MAXN = 40;
int t,n,x,ans = 1e9;
int use[20],sl[MAXN],num[MAXN];

int check(){
    memset(sl,0,sizeof(sl));        int tot = 0;
    for(int i = 0; i <= 13; i ++)   sl[use[i]] ++;

    while(sl[4] && sl[2] >= 2)//4 dai 2
        sl[4] --,sl[2] -= 2,tot ++;

    while(sl[4] && sl[1] >= 2)//4 dai 2
        sl[4] --,sl[1] -= 2,tot ++;

    while(sl[4] && sl[2])//4 dai 2
        sl[4] --,sl[2] --,tot ++;

    while(sl[3] && sl[2])//3 dai 2
        sl[3] --,sl[2] --,tot ++;

    while(sl[3] && sl[1]) //3 dai 1
        sl[3] --,sl[1] --,tot ++;

    int tot2 = sl[1] + sl[2] + sl[3] + sl[4];
    tot += tot2;
    return tot;
}
bool cmp(int a,int b){return a > b;}
void work(int step){
    if(step >= ans) return;
    int ans1 = check();
    if(ans1 + step < ans)
        ans = ans1 + step;

    int j = 2;  
    for(int i = 2; i <= 13; i ++){
        j = i;
        while(use[j] >= 3)  j ++;
        if(j - i >= 2){//san shun zi
            for(int k = i + 1; k <= j - 1; k ++){
                for(int l = i; l <= k; l ++) use[l] -= 3;
                work(step + 1);
                for(int l = i; l <= k; l ++) use[l] += 3;
            }
        }
    }
    j = 2;
    for(int i = 2; i <= 13; i ++){
        j = i;
        while(use[j] >= 2) j ++;
        if(j - i >= 3){//shuang shun zi
            for(int k = i + 2; k <= j - 1; k ++){
                for(int l = i; l <= k; l ++) use[l] -= 2;
                work(step + 1);
                for(int l = i; l <= k; l ++) use[l] += 2;
            }
        }
    }
    j = 2;
    for(int i = 2; i <= 13; i ++){
        j = i;
        while(use[j] >= 1) j ++;
        if(j - i >= 5){//dan shun zi
            for(int k = i + 4; k <= j - 1; k ++){
                for(int l = i; l <= k; l ++) use[l] --;
                work(step + 1);
                for(int l = i; l <= k; l ++) use[l] ++;
            }
        }
    }
}

int work2(){
    if(num[1]  == num[2] ) return 1;
    else    return 2;
}

int work3(){
    if(num[1]  == num[2]  && num[2]  == num[3] )    return 1;
    else if(num[1]  == num[2]  || num[2]  == num[3]  || num[1]  == num[3] ) return 2;
    else return 3;
}

int work4(){
//  if(num[1]  == num[2]  && num[2]  == num[3]  && num[3]  == num[4] ) return 1;
    memset(use,0,sizeof(use));
    for(int i = 1; i <= 4; i ++) use[num[i] ] ++;
    sort(use,use + 17,cmp); 
    if(use[0] == 4) return 1;
    if(use[0] == 3) return 1;
    if(use[0] == 2 && use[1] == 2)  return 2;
    if(use[0] == 2 && use[1] == 1 && use[2] == 1) return 3;
    else    return 4;
}

int main(){
    freopen("landlords.in","r",stdin);
    freopen("landlords.out","w",stdout); 
    scanf("%d %d",&t,&n);
    while(t --){
        memset(num,0,sizeof(num));
        memset(use,0,sizeof(use));
        memset(sl,0,sizeof(sl));
        for(int i = 1;i <= n; i ++){
            scanf("%d %d",&num[i] ,&x);
            if(num[i]  == 1) num[i]  = 13;
        //  else if(num[i]  == 2) num[i]  = 14;
        //  else if(num[i]  == 0) num[i]  = 15;
            else if(num[i] > 0) num[i]  --;
            use[num[i] ] ++; 
        }
        if(n == 2)        printf("%d\n",work2());
        else if(n == 3)   printf("%d\n",work3());
        else if(n == 4)   printf("%d\n",work4());
        else{
            ans = 1e9,work(0);
            printf("%d\n",ans);
        }
    }
    fclose(stdin);fclose(stdout);
    return 0;
}

你可能感兴趣的:(===基础===,===搜索===)