POJ 2062 Card Game Cheater

問題

二人のプレイヤーがk枚のカードを一列に向かい合うようにして並べる。
向かい合ったそれぞれのカードについて、大きいほうに1点が入る。


相手のカードとその並べ方がわかっているとき、獲得できる点数の最大値を求めよ。

制約条件

k≦26

方針

貪欲法による。
相手のカードの大きいほうから見ていき、
それに勝つようなカードがあれば、その中で最もランクの小さいものを使い、
なければ、最も弱いカードを捨石にする。

[追記]
別解がたくさんあるみたいです。
相手のカードを弱いほうから見ていく貪欲法や、
二部グラフの最大マッチングを使う方法(勝てるカードの関係に辺を貼る)、
ソートして二分探索や尺取法を使うなど。

ソースコード

vi parse(int n){
	char buf[10];
	vi res;
	while(n--){
		scanf("%s",buf);
		int pt=0;
		switch(buf[0]){
		case 'A': pt=14; break;
		case 'T': pt=10; break;
		case 'J': pt=11; break;
		case 'Q': pt=12; break;
		case 'K': pt=13; break;
		default: pt=buf[0]-'0';
		}
		pt*=4;
		switch(buf[1]){
		case 'H': pt+=3; break;
		case 'S': pt+=2; break;
		case 'D': pt++; break;
		}
		res.pb(pt);
	}
	sort(all(res));
	return res;
}
int main()
{
	int cs; scanf("%d",&cs);
	while(cs--){
		int n; scanf("%d",&n);
		vi a=parse(n),b=parse(n);
		int ans=0;
		bool use[26]={};
		for(int i=n-1;i>=0;i--){
			int mn=-1,mn2=-1;
			rep(j,n){
				if(!use[j]&&b[j]>a[i]&&(mn==-1||b[mn]>b[j]))mn=j;
				else if(!use[j]&&b[j]<=a[i]&&(mn2==-1||b[mn2]>b[j]))mn2=j;
			}
			if(mn==-1)use[mn2]=1;
			else use[mn]=1, ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}