POJ2287 Tian Ji——The Horse Racing

這是一個田忌賽馬的故事。
田忌用差的馬去匹配齊王的好馬,等到田忌的好馬能夠獲勝時,田忌就可以用好馬直接贏得比賽。
一開始用了二分圖的最大匹配做的,先判斷田忌最多能勝多少局,再判斷最多不敗多少局,用(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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章