这是一个田忌赛马的故事。
田忌用差的马去匹配齐王的好马,等到田忌的好马能够获胜时,田忌就可以用好马直接赢得比赛。
一开始用了二分图的最大匹配做的,先判断田忌最多能胜多少局,再判断最多不败多少局,用(win+notlose- n)*200即可,但是很显然时间会超出。
再仔细读题,题目中说二分图的方法对于这个问题来说“有点高级”,因此用贪心做即可。
代码1(TLE):二分图的最大匹配
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<map>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
int tianji[1010],king[1010];
bool line[1010][1010];
int m;// 双方马匹数量
int linker[1010];
bool used[1010];
int win,notlose;
bool find(int x)
{
int i,j;
for(j=1;j<=m;j++)
{
if(line[x][j]==true&&used[j]==false){
used[j] =1;
if(linker[j]==0||find(linker[j]))
{
linker[j] = x;
return true;
}
}
}
return false;
}
int main()
{
while(scanf("%d",&m),m)
{
int win=0;
memset(line,0,sizeof line);
memset(linker,0,sizeof linker);
for(int i =1;i<=m;i++)
scanf("%d",&tianji[i]);
for(int j=1;j<=m;j++)
scanf("%d",&king[j]);
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
if(tianji[i]>king[j])
line[i][j]=true;
for(int i =1;i<=m;i++)
{
memset(used,0,sizeof(used));
if(find(i))
win++;
}
//在前面基础上进行改动
memset(linker,0,sizeof linker);
int notlose = 0;
for(int i=1;i<=m;i++)
for(int j=1;j<=m;j++)
if(tianji[i]==king[j])
line[i][j]=true;
for(int i =1;i<=m;i++)
{
memset(used,0,sizeof(used));
if(find(i))
notlose++;
}
printf("%d\n",(win-m+notlose)*200);
}
return 0;
}
代码2:(AC)贪心做法:
这里涉及到一个状态的选择摘抄一段思路,原文如下
如果田忌最快的马比国王最快的马要快,那么直接比
如果田忌最快的马比国王最快的马要慢,那么用田忌最慢的马去和国王最快的马比,(反正一定要输一场,而田忌最快的马可能还能在其他比赛中胜出,所以用田忌最慢的去比至少不会吃亏)
如果田忌最快的马和国王最快的马一样快,那么要分情况
A.如果田忌最慢的马的速度小于国王最慢的马,那么就用田忌最慢的马去和国王现在最快的马比(因为田忌最慢的马现在一场也赢不了,所以还不如来抵抗国王最快的,留下自己最快的可能还能在其他比赛中胜出)
B.如果田忌最慢的马速度和国王最慢的马的速度一样,那么此时,我们还是应该用这匹最慢的马去和国王最快的马比(如果是快对快,慢对慢这样比,虽然不会亏,但是田忌最快的马已经用掉,不可能在去盈利,而如果是用田忌最慢的马去和国王最快的马比,虽然这里可能吃亏了,但是存在一种情况,即使田忌最快的马在面对除国王最慢以外的其他马时,无法盈利,但是此时田忌最快的马面对国王最慢的马时,至少不会吃亏,所以2种策略对比,后者更可取,因为除上述情况外, 田忌还是可能获利的)
C. 如果田忌最慢的马的速度大于国王最慢的马,那么就应该用田忌最慢的马去和国王最慢的马比(这里至少可以获利,去除所有C的情况,我们把情况转化为A,B,即使采取A,B策略亏本了(面对国王最快的马然后输掉比赛),C策略下的盈利还是大于等于亏本的)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int king[1010],tianji[1010];
int n;
int t1,k1,t2,k2;//通过模拟确定赛马匹配
int main()
{
while(scanf("%d",&n),n)
{
int win=0;
for(int i =0;i<n;i++)
scanf("%d",&tianji[i]);
for(int j=0;j<n;j++)
scanf("%d",&king[j]);
sort(tianji,tianji+n,cmp);
sort(king,king+n,cmp);
t1=k1=0;t2=k2 = n-1;
for(int i =0;i<n;i++)
{
if(tianji[t1]>king[k1])
{
win++;t1++;k1++;
continue;
}
if(tianji[t1]<king[k1])
{
win--;
k1++;
t2--;
continue;
}
if(tianji[t1]==king[k1])
{
if(tianji[t2]>king[k2])
{
win++;k2--;t2--;continue;
}
if(tianji[t2]<king[k2])
{
win--;
t2--;
k1++;
continue;
}
if(tianji[t2]==king[k2])
if(tianji[t2]<king[k1])
{
win--;
t2--;
k1++;
continue;
}
}
}
printf("%d\n",win*200);
}
}