题意:k表示有k张牌,然后第一行是Adam的牌,第二行是Eve的牌,每两个字符代表一张牌,第一个字符表示牌的点数,第二个表示牌的花色。Adam和Eve每次从自己的牌中选出一张牌进行比较,谁的牌大,谁就加一分,问你Eve最多能得到多少分。
思路:最大二分匹配,Eve的牌为集合1,Adam的牌为集合2,集合1中的牌与集合2中比它小的牌建立联系,找最大匹配。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define LL long long
#define maxn 105
#define INF 999999999
using namespace std;
struct Card
{
char point;
char suit;
};
struct Card Adam[30],Eve[30];
int k;
int f[maxn][maxn];
int flag[maxn];
int vis[maxn];
bool DFS(int a)
{
for(int i=1;i<=k;i++)
{
if(f[a][i]==1 && !vis[i])
{
vis[i]=1;
if(flag[i]==0 || DFS(flag[i]))
{
flag[i]=a;
return true;
}
}
}
return false;
}
int match()
{
int ans=0;
for(int i=1;i<=k;i++)
{
memset(vis,0,sizeof(vis));
if(DFS(i))
ans++;
}
return ans;
}
int get(char num)
{
if(num>='2' && num<='9')
return num-'0';
else if(num=='T')
return 10;
else if(num=='J')
return 11;
else if(num=='Q')
return 12;
else if(num=='K')
return 13;
else if(num=='A')
return 14;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&k);
memset(f,0,sizeof(f));
memset(flag,0,sizeof(flag));
for(int i=1;i<=k;i++)
{
getchar();
scanf("%c%c",&Adam[i].point,&Adam[i].suit);
}
for(int i=1;i<=k;i++)
{
getchar();
scanf("%c%c",&Eve[i].point,&Eve[i].suit);
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
if(Eve[i].point!=Adam[j].point)
{
int a=get(Eve[i].point);
int b=get(Adam[j].point);
if(a>b)
f[i][j]=1;
}
else if(Eve[i].point==Adam[j].point)
{
if(Eve[i].suit=='H' && Adam[j].suit!='H')
f[i][j]=1;
else if(Eve[i].suit=='S' && Adam[j].suit!='H' && Adam[j].suit!='S')
f[i][j]=1;
else if(Eve[i].suit=='D' && Adam[j].suit=='C')
f[i][j]=1;
}
}
}
printf("%d\n",match());
}
return 0;
}
// H S D C