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;
}