题目大意
田忌和齐王赛马,各自有n匹马,每匹马有一个能力值,能力值大的获胜,赢一局得200分输一局-200分平局得0分.问田忌最多得到多少分?
分析
根据题意很容易想到二分图匹配,将每一组田忌比齐王大的连上一条边,这样通过二分图匹配可以求得田忌最多胜多少局。但仔细想了之后发现平局的情况会比较难以处理。
这是一道贪心题,只是需要花些功夫来证明贪心策略的正确性,一开始的策略想复杂了(田忌的每匹马去赢它刚好能够赢的齐王的马,出一看没什么问题,具体做的时候会发现细节还是很难处理)
看了网上很多博客发现基本都没去证明其中一个策略的正确性(贪心题你不证明清楚这不是耍流氓吗),后来培训的时候还一知半解地还给大一把这道题地证明讲了,问听懂没有,回答听懂了(我也是醉了,我自己都没懂我是怎么把他们讲懂的?)后来仔细想了很久总算搞懂了。
现在来详细分析一下这道题的解题思路:
这里用T来表示田忌的马,Q来表示齐王的马
先分类
①
T小<Q小:
说明
T小比Q的任何一只都小
,无论这样都是输,要输的最有价值,用
T小去把齐王最大的Q大拖下水
②
T小>Q小:
齐王最小的马无论和田忌哪匹马比都是输,田忌肯定是选择用他最小的马去比。
③
T小=Q小
这个时候情况就要复杂一点了,再分为三种情况:
a
:
b
:
c
:
现在我们要证明在
T小=Q小且T大=Q大
的情况下
(T小,Q大)是比(T大,Q大)更优的选择
我们先画出分别做出这两个选择后的局面:
假设第一种局面得到的结果是
ans1
第二种是
ans2
,我们要证明的是
ans1≥ans2+1
(因为我们到达局面一是输了一局,而到局面二是平的)
此时,最终
T小
只有两种情况,要么和
Q小
去平要么输给齐王的匹马:
1.如果
T小
是和
Q小
平,我们可以通过在局面二引入
T大
,让
T大
去赢
Q小
,然后删掉
T小
此时的局面就是局面一,
ans1=ans2+1
2.如果
T小
是输给齐王的某匹马,我们可以通过在局面二引入
T大
,让
T大
去赢这匹马,然后删掉
T小
此时的局面就是局面一,
ans1>ans2+1
(因为撤销了一场输掉的比赛,增加了一场赢的比赛)
这样我们就证明了
ans1≥ans2+1
所以我觉得这个证明过程不是显而易见的啊!!!
代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
using namespace std;
int n;
int ans;
int T[1005];
int K[1005];
int main()
{
while(scanf("%d",&n)!=EOF && n)
{
for(int i=1;i<=n;i++)scanf("%d",&T[i]);
for(int i=1;i<=n;i++)scanf("%d",&K[i]);
sort(T+1,T+n+1);
sort(K+1,K+n+1);
int win=0,lose=0;
int t_low=1,t_fast=n;
int k_low=1,k_fast=n;
while(t_low <= t_fast )
{
if(T[t_low] < K[k_low])
{
lose++;
t_low++;
k_fast--;
}
else if(T[t_low] > K[k_low])
{
win++;
t_low++;
k_low++;
}
else
{
if(T[t_fast] > K[k_fast])
{
t_fast--;
k_fast--;
win++;
}
else
{
if(T[t_low]<K[k_fast])lose++;
t_low++;
k_fast--;
}
}
}
printf("%d\n",200*(win-lose));
}
return 0;
}