HDU 1528 Card Game Cheater(二分图最大匹配)

HDU 1528 Card Game Cheater(二分图最大匹配)

http://acm.hdu.edu.cn/showproblem.php?pid=1528

题意:

       Adam和Eve打牌,Eve可以看到Adam的牌.现在Adam已经把牌按顺序摆好了,Eve知道Adam所有的牌,所以Eve可以最优化自己牌的摆放顺序,使得自己每个位置上的牌赢Adam对应位置上的牌的个数最多.

       其中每张牌由值+类型构成,值是2, 3, 4, 5, 6, 7, 8 ,9, T, J, Q, K, A,这些值依次增加其中2最小,A最大.类型为: C, D, S, H. 类型同样依次增大,H类最大.

       问题Eve最多能拿几分?(一张牌赢拿1分,输了或平局不拿分)

分析:

       构建二分图:左点集是Eve对应的n张牌,右点集是Adam对应的n张牌. 如果左i牌>右j牌,那么就连一条左i右j的边.

       本题要获得最多的分,就是要找到一个最大匹配.每条匹配边就是1分.所以本题最终解== 二分图最大匹配边数.

       本题我把每张牌的直接转化为分数,然后比较分数即可.

       2-A 代表20分,30分,…140分. 而 CDSH分别代表1,2,3,4分.

AC代码:

#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
#include<iostream>
using namespace std;
const int maxn = 26+5;

struct Max_Match
{
    int n;
    vector<int> g[maxn];
    bool vis[maxn];
    int left[maxn];

    void init(int n)
    {
        this->n=n;
        for(int i=1;i<=n;i++) g[i].clear();
        memset(left,-1,sizeof(left));
    }

    bool match(int u)
    {
        for(int i=0;i<g[u].size();i++)
        {
            int v=g[u][i];
            if(!vis[v])
            {
                vis[v]=true;
                if(left[v]==-1 || match(left[v]))
                {
                    left[v]=u;
                    return true;
                }
            }
        }
        return false;
    }

    int solve()
    {
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(match(i)) ++ans;
        }
        return ans;
    }
}MM;
int get_score(string& s)
{
    int ans=0,i=0;
    if(s[i]>='2'&&s[i]<='9') ans += (s[i]-'0')*10;
    else if(s[i]=='T') ans += 100;
    else if(s[i]=='J') ans += 110;
    else if(s[i]=='Q') ans +=120;
    else if(s[i]=='K') ans +=130;
    else if(s[i]=='A') ans +=140;
    i=1;//C, D, S, or H
    if(s[i]=='C') ans+=1;
    else if(s[i]=='D') ans+=2;
    else if(s[i]=='S') ans+=3;
    else if(s[i]=='H') ans+=4;
    return ans;
}
int main()
{
    int T; scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        MM.init(n);
        int s1[maxn],s2[maxn];
        string s;
        for(int i=1;i<=n;i++)
        {
            cin>>s;
            s2[i]=get_score(s);
        }
        for(int i=1;i<=n;i++)
        {
            cin>>s;
            s1[i]=get_score(s);
        }

        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        if(s1[i]>s2[j])
            MM.g[i].push_back(j);
        printf("%d\n",MM.solve());
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值