问题描述
这里有一个中国历史上著名的故事。 “那是2300年前的事了。田基将军是齐国的高官。他喜欢和国王和其他人一起赛马。” “天王两人都有三匹不同等级的马,分别是普通马、加号马和超级马。规则是一场比赛分三轮,每匹马必须用一轮。一轮胜出者从失败者手中夺走两百银元。” 国王是全国最有权势的人,他的马非常好,每一级的马都比田的好,因此,每次国王从田那里得到六百银元 “田基对此并不高兴,直到他遇到了中国历史上最著名的将军之一孙彬。由于孙的一个小把戏,田吉在下一场比赛中赢了两百块银元和一个这样的恩典。” “这是一个相当简单的把戏。用他平时的班马与国王的超级班马比赛,他们肯定会输掉那一轮。但是他的加号打败了国王的常规赛,他的超级赛打败了国王的加号赛。多简单的把戏啊。你觉得中国的高官田吉怎么样?” 如果田基生活在现在,他一定会嘲笑自己。更重要的是,如果他现在参加ACM竞赛,他可能会发现赛马问题可以简单地看作是在一个二分图中找到最大匹配。一边画田的马,一边画王的马。只要田中的一匹马能打败国王的一匹马,我们就在它们之间划一条边,这意味着我们希望建立一对。那么,赢得尽可能多轮的问题就是在这个图中找到最大匹配。如果有联系,问题会变得更复杂,他需要给所有可能的边分配0、1或-1的权重,并找到一个最大权重的完美匹配。。。 然而,赛马问题是一个非常特殊的情况下,双方匹配。图是由马的速度决定的——速度越快的顶点总是比速度越慢的顶点强。在这种情况下,加权二部匹配算法是一个太先进的工具来处理这个问题。 在这个问题中,要求您编写一个程序来解决这个特殊情况下的匹配问题。
输入
输入由多达50个测试用例组成。每种情况都以第一行的正整数n(n<=1000)开始,这是每边的马数。第二行接下来的n个整数是田的马的速度。接下来第三行的n个整数是国王的马的速度。输入以最后一个测试用例后有一个0的行结束。
输出
对于每一个输入案例,输出一行包含一个数字的行,这是田忌将获得的最大金额,单位为银元。
样本输入
3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0
样本输出
200
0
0
自身误区:第一遍的时候,不过是因为没有考虑到等于的时候还有最优的策略,没有分析导致不过。
后来几次的错误,是因为同个错误:一下代码中有详细描述。
本题思路核心:快的比得过直接比,比不过用自己最慢的顶。
整体思路:首先,排序,选择最快的进行比较,比得过直接就赢,然后下一个,比不过,用最慢的顶对面最快的(相当于对面最快的没发挥作用),在这里特别说明一下相等的情况,很多人最开始会想当然的觉得相等情况不需要考虑(这些人包括我在内~),
正确思路:首先相等也就意味这并局没输没赢,想要利益最大化,就可以用最弱的顶掉最强的,为自己最强的增加胜利的机会,输了一局也没事,因为对面还剩一个最慢的所以他们也一定会输一局,也就是说在提高我方胜率的同时,有保证了平局,这不相当于将利益更大化了吗。
贪心算法,
# include <iostream>
# include <algorithm>
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n,c=0,i,j,x,m;
while(scanf("%d",&n)&&n!=0)
{
c=0;//重复计算需要清零
int a[n],b[n];
for( i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
scanf("%d",&b[i]);
sort(a,a+n,cmp);
sort(b,b+n,cmp);//从大到小时必须cmp (如果用从小到大排序,没办法很好控制结束的地方)
j=i=0; // 分别是两者快马的标记
m=n-1,x=n-1;//慢马标记
while(n--)//最好不要用for循环,不好控制下标
{
if(a[i]>b[j])
{
c++;i++;j++;continue;
}
else if(a[i]<b[j])
{
c--;//怎么表示用田慢兑掉了王快
j++;//利用下标移动来实现
m--; continue;
}
else
{
if(a[m]>b[x])
{
c++;
m--;//田最慢的下标发生变化
x--;//王最慢的下标发生变化
}
else if(a[m]<b[j])//原错误写法:(a[m]<b[x])
{//上面一行我找错找了半天才找到错误
//原因就是,理解错了
//我一开始的想法时,只用两人的慢马比较
//比不过就用田的慢换掉王的快,
//但是其实是有一个数据用了两次,(结尾的测试数据)
//而还有数据没有使用
c--;
m--;
j++;
}
else
{
m--;//修改一
j++;
} continue;
}
}
printf("%d\n",c*200);
}
}
3
14 12 13
15 14 13(朋友给的测试数据,很好用,感觉会测倒一片~)