bzoj1034 田忌赛马 题解报告
【题目大意】
有$n$场比赛,给出你的对手每匹马的能力值和你的每匹马的能力值,每场比赛胜利则得两分,平手得一分,输了不得分。求$n$场比赛后你的最大和最小得分。
【思路分析】
其实这题原名叫泡泡堂[滑稽.jpg]
设$a$数组记录对手的马的能力值,$b$数组记录你的马的能力值,将两个数组从小到大排序。
首先分析最大得分,我们有这样的贪心策略:
1.如果当前状态下$a_{max}<b_{max}$,那么就用$b_{max}$去和$a_{max}$比,直到不满足条件
2.如果当前状态下$a_{min}<b_{min}$,那么就用$b_{min}$去和$a_{min}$比,直到不满足条件
3.当上面两个条件都不满足时,就用$b_{min}$去和$a_{max}$比,然后继续上面的步骤
最后即可得出最大得分$ans_1$
对于最小得分,我们可以发现一个规律:无论如何,$n$场比赛结束后两人的总得分为$2*n$,那么可以用上面的方法求出对手的最大得分$ans$,那么最小得分即为$ans_2=2*n-ans$
【代码实现】
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define g() getchar() 7 #define rg register 8 #define go(i,a,b) for(rg int i=a;i<=b;i++) 9 #define back(i,a,b) for(rg int i=a;i>=b;i--) 10 #define db double 11 #define ll long long 12 #define il inline 13 #define pf printf 14 using namespace std; 15 int fr(){ 16 int w=0,q=1; 17 char ch=g(); 18 while(ch<'0'||ch>'9'){ 19 if(ch=='-') q=-1; 20 ch=g(); 21 } 22 while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g(); 23 return w*q; 24 } 25 const int N=100002; 26 int n,a[N],b[N],ans1,ans2; 27 int main(){ 28 //freopen("","r",stdin); 29 //freopen("","w",stdout); 30 n=fr(); 31 go(i,1,n) b[i]=fr(); 32 go(i,1,n) a[i]=fr(); 33 sort(a+1,a+1+n);sort(b+1,b+1+n); 34 rg int la=1,ra=n,lb=1,rb=n; 35 while(la<=ra&&lb<=rb){ 36 while(la<=ra&&lb<=rb&&a[ra]<b[rb]) ra--,rb--,ans1+=2; 37 while(la<=ra&&lb<=rb&&a[la]<b[lb]) la++,lb++,ans1+=2; 38 if(a[ra]==b[lb]) ans1++; 39 lb++;ra--; 40 } 41 la=lb=1;ra=rb=n; 42 while(la<=ra&&lb<=rb){ 43 while(la<=ra&&lb<=rb&&a[ra]>b[rb]) ra--,rb--,ans2+=2; 44 while(la<=ra&&lb<=rb&&a[la]>b[lb]) la++,lb++,ans2+=2; 45 if(a[la]==b[rb]) ans2++; 46 la++;rb--; 47 } 48 ans2=2*n-ans2; 49 pf("%d %d\n",ans1,ans2); 50 return 0; 51 }