首页 > 搜索 > DFS搜索 > HDU 1528 Card Game Cheater-二分图-[解题报告] C++
2013
12-12

HDU 1528 Card Game Cheater-二分图-[解题报告] C++

Card Game Cheater

问题描述 :

Adam and Eve play a card game using a regular deck of 52 cards. The rules are simple. The players sit on opposite sides of a table, facing each other. Each player gets k cards from the deck and, after looking at them, places the cards face down in a row on the table. Adam’s cards are numbered from 1 to k from his left, and Eve’s cards are numbered 1 to k from her right (so Eve’s i:th card is opposite Adam’s i:th card). The cards are turned face up, and points are awarded as follows (for each i ∈ {1, . . . , k}):

If Adam’s i:th card beats Eve’s i:th card, then Adam gets one point.

If Eve’s i:th card beats Adam’s i:th card, then Eve gets one point.

A card with higher value always beats a card with a lower value: a three beats a two, a four beats a three and a two, etc. An ace beats every card except (possibly) another ace.

If the two i:th cards have the same value, then the suit determines who wins: hearts beats all other suits, spades beats all suits except hearts, diamond beats only clubs, and clubs does not beat any suit.

For example, the ten of spades beats the ten of diamonds but not the Jack of clubs.

This ought to be a game of chance, but lately Eve is winning most of the time, and the reason is that she has started to use marked cards. In other words, she knows which cards Adam has on the table before he turns them face up. Using this information she orders her own cards so that she gets as many points as possible.

Your task is to, given Adam’s and Eve’s cards, determine how many points Eve will get if she plays optimally.

输入:

There will be several test cases. The first line of input will contain a single positive integer N giving the number of test cases. After that line follow the test cases.

Each test case starts with a line with a single positive integer k <= 26 which is the number of cards each player gets. The next line describes the k cards Adam has placed on the table, left to right. The next line describes the k cards Eve has (but she has not yet placed them on the table). A card is described by two characters, the first one being its value (2, 3, 4, 5, 6, 7, 8 ,9, T, J, Q, K, or A), and the second one being its suit (C, D, S, or H). Cards are separated by white spaces. So if Adam’s cards are the ten of clubs, the two of hearts, and the Jack of diamonds, that could be described by the line

TC 2H JD

输出:

For each test case output a single line with the number of points Eve gets if she picks the optimal way to arrange her cards on the table.

样例输入:

3
1
JD
JH
2
5D TC
4C 5H
3
2H 3H 4H
2D 3D 4D

样例输出:

1
1
2

题目:点击打开链接

题意:两个人纸牌游戏,牌大的人得分。牌大:2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q

          < K < A 。值一样看花色, hearts (红心) > spades (黑桃) > diamond
(方块) >

            clubs
(梅花)。问Eve 能得多少分。(每次得1分)

分析:将Eve的每张牌与Adam的所有牌比较,与所有比这张牌小的Adam的牌连边。

 
         然后求最大匹配。

感想:几天前就写了,开始WA以为是对于王没有四种花色的处理应该分开。昨天

           突然发现问题根本不在那,因为这里面根本没说王,是数组开小了。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

char t1[15]={'2','3','4','5','6','7','8','9','T','J','Q','K','A'};
int t2[15]={1,2,3,4,5,6,7,8,9,10,11,12,13};
struct node
{
    int id;
    char cha;
    char type;
}card[60];
int n,cnt;
int match[60];
int vis[60];
int g[60][60];

bool judge(int x,int y)
{
    if(card[x].type=='H' && card[y].type!='H')
        return true;
    else if(card[x].type=='S' && (card[y].type=='D'||card[y].type=='C'))
        return true;
    else if(card[x].type=='D' && card[y].type=='C')
        return true;
    else return false;
}
bool dfs(int u)
{
    for(int i=1;i<=n;i++)
    {
        if(g[u][i] && !vis[i])
        {
            vis[i]=true;
            if(match[i]==-1 || dfs(match[i]))
            {
                match[i]=u;
                return true;
            }
        }
    }
    return false;
}
int main()
{
    int T,i,j,k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        getchar();
        memset(card,0,sizeof(card));
        memset(match,-1,sizeof(match));
        memset(g,0,sizeof(g));
        for(j=1;j<=n;j++)
        {
            card[j].cha=getchar();
            for(k=0;k<13;k++)
                if(card[j].cha==t1[k])
                    card[j].id=t2[k];
            /*if(card[j].id==13)
            {
                if(j<=n-1)
                    getchar();
                continue;
            }*/
            card[j].type=getchar();
            if(j<=n-1)
                getchar();
        }
        getchar();
        for(j=n+1;j<=2*n;j++)
        {
            card[j].cha=getchar();
            for(k=0;k<13;k++)
                if(card[j].cha==t1[k])
                    card[j].id=t2[k];
            /*if(card[j].id==13)
            {
                if(j<=n-1)
                    getchar();
                continue;
            }*/
            card[j].type=getchar();
            getchar();
            for(i=1;i<=n;i++)
            {
                if(card[j].id>card[i].id)
                    g[j][i]=true;
                else if(card[j].id==card[i].id && judge(j,i))
                    g[j][i]=true;
            }
        }
        cnt=0;
        for(i=n+1;i<=2*n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
                cnt++;
        }
        printf("%d\n",cnt);
    }
    return 0;
}

解题报告转自:http://blog.csdn.net/u011262722/article/details/10815855


  1. a是根先忽略掉,递归子树。剩下前缀bejkcfghid和后缀jkebfghicd,分拆的原则的是每个子树前缀和后缀的节点个数是一样的,根节点出现在前缀的第一个,后缀的最后一个。根节点b出现后缀的第四个位置,则第一部分为四个节点,前缀bejk,后缀jkeb,剩下的c出现在后缀的倒数第2个,就划分为cfghi和 fghic,第3部分就为c、c

  2. 第二个方法挺不错。NewHead代表新的头节点,通过递归找到最后一个节点之后,就把这个节点赋给NewHead,然后一直返回返回,中途这个值是没有变化的,一边返回一边把相应的指针方向颠倒,最后结束时返回新的头节点到主函数。

  3. 您没有考虑 树的根节点是负数的情况, 若树的根节点是个很大的负数,那么就要考虑过不过另外一边子树了