(hdu step 6.3.5)Card Game Cheater(匹配的最大数:a与b打牌,问b赢a多少次) Card Game Cheater
称号:
题目大意:
a和b手上都有n张牌,b的一张牌赢了a的一张牌,b就得一分,问b能得多少分。
例子分析:
输入:
3 1//两个人手中的牌的张数 JD//adams手上的牌 JH//eves手上的牌 2 5D TC 4C 5H
输出:
第二个例子中的输出结果为1.为什么呢。
由于eves手上仅仅有5H比adams手上的5D大。得1分。他手上的4C要比
adams手上的TC要小,不能得分。
题目分析:
二分图,求最大匹配。需要注意的是。
1、这道题中的匹配规则已经不是“a愿不愿意与b匹配”了。而是,仅仅有在b>a的时候才干匹配
2、这道题中b和a都是字符串。
怎样比較大小呢?先比較第1个字符然后,假设第1个字符相等再比較第2个字符。
3、这道题是用的是邻接表求的最大匹配数。
代码例如以下:
/*
* e.cpp
*
* Created on: 2015年3月14日
* Author: Administrator
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 27;
vector<int> map[maxn];
bool useif[maxn];
int link[maxn];
int n;
/**
* 获取一张牌前缀的索引
*/
int card_pre(char a){
string pre = "23456789TJQKA";
int len = pre.length();
int i;
for(i = 0 ; i < len ; ++i){
if(a == pre.at(i)){
return i;
}
}
return 0;
}
/**
* 获取一张牌后缀的索引
*/
int card_suf(char a){
string suf = "CDSH";
int len = suf.length();
int i;
for(i = 0 ; i < len ; ++i){
if(a == suf.at(i)){
return i;
}
}
return 0;
}
/**
* 比較a和b这两张牌哪一张牌比較大
*/
bool isBig(string a,string b){
int aa = card_pre(a[0]);//获取一张牌的前缀
int bb = card_pre(b[0]);//获取一张牌的后缀
if(aa == bb){//假设这两张牌的前缀同样
return card_suf(a[1]) < card_suf(b[1]);//则比較后缀
}
//假设这两张牌的前缀已经不同样则直接比較前缀
return aa < bb;
}
/**
* 推断一个节点t是否能找到和她匹配的节点
*/
bool can(int t){
int i;
int size = map[t].size();//获取愿意与节点t匹配的结点的数量
for(i = 0 ; i < size ; ++i){//遍历每个愿意和结点t匹配的结点
int index = map[t][i];//获取当前愿意和结点t匹配的节点的索引
if(useif[index] == false){//假设这个节点还没有匹配
useif[index] = true;//那么将这个节点标记为已经匹配
//假设这个节点还没有匹配的节点||月这个节点匹配的节点可以找到其它结点与它匹配
if(link[index] == -1 || can(link[index])){
link[index] = t;//那么将当前节点匹配的结点设置为t
return true;//返回true,表示根节点t可以找到与它匹配的节点
}
}
}
return false;//返回false,表示节点t无法找到与它匹配的结点
}
/**
* 求醉大匹配数
*
*/
int max_match(){
int num = 0;
int i;
for(i = 0 ; i < n ; ++i){//遍历每个结点
memset(useif,false,sizeof(useif));
if(can(i) == true){
num++;
}
}
return num;
}
int main(){
int t;
scanf("%d",&t);
string adams[maxn];
while(t--){
// int n;//这里千万不要在定义一个局部变量,否则会覆盖全局变量
scanf("%d",&n);
int i;
//初始化变量
memset(link,-1,sizeof(link));
for(i = 0 ; i < n ; ++i){
map[i].clear();
}
for(i = 0 ; i < n ; ++i){//初始化adams的牌
cin >> adams[i];
}
string eves;
/**
* 每次读入eves当前的牌,都接着计算它能与adams的那些牌匹配.
* 这列的匹配规则已经不是:a愿不愿意 与b匹配了.
* 而是仅仅有当b>a的时候,b才干与a匹配
* (为什么呢?由于eves要得分,那么他手上的牌就必需要比adams的大)
*/
for(i = 0 ; i < n ; ++i){
cin >> eves;
int j;
for(j = 0 ; j < n ; ++j){
if(isBig(adams[j],eves) == true){
map[i].push_back(j);
}
}
}
printf("%d
",max_match());//计算最大匹配数
}
return 0;
}
版权声明:本文博客原创文章,博客,未经同意,不得转载。