中山大学校队内部选拔赛3.5【Horse Racing】------2015年2月10日
一:题目大意
给定A和B两人各自n条马,每一条马的能力值不同,现在由裁判C主持比赛。每一次比赛A和B各自出一条马,能力值大的一方会获胜。现在规定如果当进行到最后时A和B打成平手的话我们就说C赢。现在问怎样才能保证C赢?
二:题目分析
本题主要考查贪心(不太好想)策略。我们首先可以得到一个起码的规律那就是如果n是奇数,那么这个肯定不会赢。当n时偶数时:
我们要想C赢,那么A和B需要各自赢一半。现在我们对于A的输入的马能力值定义为:a1,a2,a3······an.B的输的能力值定义为:b1,b2,·····bn。
我们可以先把A的马分成均分成两半,设前一半中马的能力的最大值为aj,后一半中马的能力的最小值为ak,现在我们把这两匹马进行交换。如此往复进行,直到前一半的马全部比后一半的马的能力值小为止。那么我们同样可以采取类似的方法对B的马进行处理,使得前一半的马的能力值比后一半的能力值高。设更新得到的状态是:
a1',a2',······an'和b1',b2'·····bn'。
现在我们对于A和B的前一半马进行分析:
我们首先找出A和B前一半的马的能力的最大值分别为:ak'和bj'。我们把ak'和aj'进行交换,使得前一半的值从A到B各自对应。
同理我们使得后一半中同样从A到B各自对应。
到这里我们可以得到如果前一半中或者后一半中存在一个对应值不满足要求,那么肯定C不会赢。
对应于以上的处理,我们其实可以采取一个快排,然后让A的前一半和B的后一半进行比较,A的后一半和B的前一半进行比较。最后得出答案。
三:AC代码
#include<iostream> #include<algorithm> using namespace std; int a[100],b[100]; int n; int main() { while(cin>>n) { for(int i=0;i<n;i++) { cin>>a[i]; } for(int i=0;i<n;i++) cin>>b[i]; sort(a,a+n); sort(b,b+n); int ok=1; if(n%2==1) { ok=0; } for(int i=0;i<n/2;i++) if(a[i]>b[i+n/2]) ok=0; for(int i=0;i<n/2;i++) if(b[i]>a[n/2+i]) ok=0; if(!ok) cout<<"NO"<<endl; else cout<<"YES"<<endl; } return 0; }
四:总结
博弈问题需要好好体会