OpenJudge Tian Ji -- The Horse Racing
目錄
?
Tian Ji -- The Horse Racing
要求:
描述:
輸入 :
輸出:?
樣例輸入:?
樣例輸出:
問題分析:
情況一:
情況二:
情況三:
最終代碼:
總結:
其他思路:
Tian Ji -- The Horse Racing
要求:
總時間限制:?5000ms
內存限制:?65536kB
描述:
Here is a famous story in Chinese history.?
That was about 2300 years ago. General Tian Ji was a high official in the country Qi. He likes to play horse racing with the king and others.?Both of Tian and the king have three horses in different classes, namely, regular, plus, and super. The rule is to have three rounds in a match; each of the horses must be used in one round. The winner of a single round takes two hundred silver dollars from the loser.?
Being the most powerful man in the country, the king has so nice horses that in each class his horse is better than Tian's. As a result, each time the king takes six hundred silver dollars from Tian.?
Tian Ji was not happy about that, until he met Sun Bin, one of the most famous generals in Chinese history. Using a little trick due to Sun, Tian Ji brought home two hundred silver dollars and such a grace in the next match.?
It was a rather simple trick. Using his regular class horse race against the super class from the king, they will certainly lose that round. But then his plus beat the king's regular, and his super beat the king's plus. What a simple trick. And how do you think of Tian Ji, the high ranked official in China??
Were Tian Ji lives in nowadays, he will certainly laugh at himself. Even more, were he sitting in the ACM contest right now, he may discover that the horse racing problem can be simply viewed as finding the maximum matching in a bipartite graph. Draw Tian's horses on one side, and the king's horses on the other. Whenever one of Tian's horses can beat one from the king, we draw an edge between them, meaning we wish to establish this pair. Then, the problem of winning as many rounds as possible is just to find the maximum matching in this graph. If there are ties, the problem becomes more complicated, he needs to assign weights 0, 1, or -1 to all the possible edges, and find a maximum weighted perfect matching...?
However, the horse racing problem is a very special case of bipartite matching. The graph is decided by the speed of the horses -- a vertex of higher speed always beat a vertex of lower speed. In this case, the weighted bipartite matching algorithm is a too advanced tool to deal with the problem.?
In this problem, you are asked to write a program to solve this special case of matching problem.
輸入 :
The input consists of up to 50 test cases. Each case starts with a positive integer n ( n<=1000) on the first line, which is the number of horses on each side. The next n integers on the second line are the speeds of Tian's horses. Then the next n integers on the third line are the speeds of the king's horses. The input ends with a line that has a single `0' after the last test case.
輸出:?
For each input case, output a line containing a single number, which is the maximum money Tian Ji will get, in silver dollars.
樣例輸入:?
3 92 83 71 95 87 74 2 20 20 20 20 2 20 19 22 18 0樣例輸出:
200 0 0問題分析:
這是眾所周知的田忌賽馬問題,我們先來理一下這個英文題面。田忌和齊王賽馬,約定誰贏一局?就會從對手那里贏取200銀元. 如果雙方平局,則錢數不會發生變化。那么對于給定的馬速序列,我們希望知道田忌最多能夠贏多少銀元,或者說最少會輸掉多少銀元。
輸入有若干組,以0結束;每一組中第一行n代表雙方各有多少匹馬,接下來的兩行分別代表田忌的馬的速度與齊王的馬的速度,(注意:雖然樣例是從大到小給出,但測試時數據并不一定按照從大到小給出)最后輸出田忌所贏錢數就可以了。
while(scanf("%d",&n)&&n!=0){//輸入部分cin.get();//因為用的是scarf,所以需要讀掉每行最后的回車int Tian[n];int King[n];for(int i=0;i<n;i++){scanf("%d",&Tian[i]);}cin.get();for(int i=0;i<n;i++){scanf("%d",&King[i]);}cin.get(); }一個自然的思路是通過搜索(枚舉),遍歷所有可能,從而找到收益最大的值。但我們注意到雙方的馬匹數是0~1000,這個數據還是非常大的,因為遍歷所有可能的時間復雜度是O(n!),也就是最多需要進行1000!次枚舉,這個時間是我們不能忍受的,即使本題時間要求是5000ms。
所以我們希望找到一些好的算法(貪心),結合歷史上的田忌賽馬事件,我們可以簡單地得出一個粗糙的“結論”:如果我們用自己的劣馬耗掉對方的良馬,我方的優勢就會擴大。那么基于這樣一個“結論”,我們可以對這個想法進行精細化討論和實現。
首先我們需要對雙方的馬進行排序,以便我們后續查找對應的馬。(這里用到了lambda表達式進行從大到小排序,如果不清楚的話,自己寫一個比較函數或者默認從小到大排序也可以)
sort(King,King+n,[](int a,int b){return a>b;});//對于傳入的int型a和b,返回a>b的bool值 sort(Tian,Tian+n,[](int a,int b){return a>b;});情況一:
所以我們就來考慮田忌方最差的馬,我們希望可以最大化利用這匹馬,那么當我們這匹馬連對面最差的馬都不如的話,直接用它來消耗對面最好的馬。(這匹馬不管面對誰,結果都為負,所以消耗掉對面最好的馬就是收益最好的結果)?
田忌賽馬歷史故事告訴我們的只有以上規則,但我們可以看到這個規則很不完善:我們仍需分類討論,當我們的最劣馬等于對方最劣馬時以及優于對方最劣馬的情況。
情況二:
如果我方的最劣馬優于對方的最劣馬,若此時我們仍用此馬來消耗對面最優馬,這個情況是不好的,因為我們總能找到一個至少不差并且可能更優的局面:
假設我們現在不考慮己方最差馬N和對方最優馬P后得到的最大收益是K,那么用最差馬消耗對面最優馬的最佳收益就是(K+(N與P比賽結果))*200,那么在該局面下,我方總有一匹馬M和對方最差馬Q比賽并且獲勝(M>=N>Q),那么當我們用N來和Q比,用M來跟P比,其他比賽不變,我們此時的收益為((K-1)+1+(M與P比賽結果))*200,由于M>=N,所以這個結果至少不會差于上一個局面。
所以如果我方的最劣馬優于對方的最劣馬,我們總是用己方最劣馬來和對方最劣馬比賽并獲勝。
情況三:
如果我方的最劣馬剛好和對方最劣馬相當時,我們怎么處理?
考慮這兩組數據:
2 20 10 15 10 2 15 10 20 10對于第一組,我們不能用己方最差換對面最好,這樣做(一輸一勝)的收益是0,小于最大收益(一平一勝)200;但是對于第二組,我們必須用己方最差換對面最好,(一輸一勝)收益為0,大于(一平一輸)收益為-200.
所以從上述的例子中我們可以發現此時需要針對最優馬再進行分類討論,如果我方最優馬比對方更好,直接最優馬先贏下這一局,否則就用最劣馬去換掉對面最優的。(證明方式類似上面)
最終代碼:
所以在上面的分類討論中,我們已經把情況討論齊全。
#include<iostream> #include<algorithm> using namespace std; int main(){int n;while(scanf("%d",&n)&&n!=0){//輸入部分cin.get();int *Tian=new int[n];//田忌int *King=new int[n];//齊王for(int i=0;i<n;i++){scanf("%d",&Tian[i]);}cin.get();sort(Tian,Tian+n,[](int a,int b){return a>b;});for(int i=0;i<n;i++){scanf("%d",&King[i]);}cin.get();sort(King,King+n,[](int a,int b){return a>b;});//算法部分int Money=0;int KingLast=n-1;int KingFirst=0;int TianFirst=0;for(int TianLast=n-1;TianLast>=TianFirst;){if(Tian[TianLast]<King[KingLast]){//情況一Money--;KingFirst++;TianLast--;}else if(Tian[TianLast]>King[KingLast]){//情況二KingLast--;Money++;TianLast--;}else{//情況三if(Tian[TianFirst]<=King[KingFirst]){//如果最優沒有對面好,用最后去換if(Tian[TianLast]<King[KingFirst]) Money--;KingFirst++;TianLast--;}else{//如果己方最優馬比對方最優馬好Money++;KingFirst++;TianFirst++;}}}printf("%d\n",Money*200);//釋放內存delete []Tian;delete []King;} }總結:
?一道經典的貪心算法,最難的就是對各種情況的討論以及證明,一定切記避免想當然,不然很容易漏掉一些情況。希望這篇文章對您有所幫助。最后求贊求關注😂(對于貪心題目,時空間復雜度不重要,重要的是自己算法的完備性和合理性)
其他思路:
其實不一定需要先考慮最劣馬的分類情況,也可以反過來先考慮最優馬,但是我覺得沒有最劣馬討論直觀,故在此沒有列出。
總結
以上是生活随笔為你收集整理的OpenJudge Tian Ji -- The Horse Racing的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python是脚本语言、主要用作系统编程
- 下一篇: 方正科技服务器可以重装系统吗,云骑士的系