這是一個田忌賽馬的故事。
田忌用差的馬去匹配齊王的好馬,等到田忌的好馬能夠獲勝時,田忌就可以用好馬直接贏得比賽。
一開始用了二分圖的最大匹配做的,先判斷田忌最多能勝多少局,再判斷最多不敗多少局,用(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);
}
}