P1650 田忌赛马
我在考试的时候看到了这道题,在一瞬间就蒙逼了,这是什么题?(请原谅我\(-250\)的智商)于是懵里懵懂的打了个\(d\)(电)\(f\)(风)\(s\)(扇),结果连样例都没有过。(毕竟才学搜索没多久嘛,也就两年)。再一看,看出了田忌赛马的味道,原来是这样!立刻打了个贪心信心满满的交上去。
#include<bits/stdc++.h>
using namespace std;
int a[514514],b[514514],n,t,k;
long long ans;
bool cmp(int x,int y){return x>y;}
int main(){
ans=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1,cmp);
sort(b+1,b+n+1,cmp);
k=n;
for(int i=1;i<=n;i++){
if(a[i]>=b[i-(n-k)]){
if(a[i]==b[i]){
if(a[n]>=b[k]) ans--;
}
if(a[i]!=b[k]) ans--;
k--;
}
else ans++;
}
cout<<ans*200<<endl;
return 0;
}
\(AC\)了!(那是不可能的)只拿了\(80\)分。(在洛谷是爆零的)原因?各位读者自己推一下也就推出来了:田忌与齐王的尾指针是一样的!而且平局时的处理也不够。。。。。。漏洞百出,\(80\)分真是万幸了。
好,接下来是正解了!
运用我们的老祖宗田忌的思路!
设\(la\),\(ra\)为田忌的头,尾指针,\(lb\),\(rb\)为齐王的头,尾指针,将两个速度值从大到小排序,如果\(a_{la}>b_{lb}\)那么\(ans++\),\(la--\),\(ra--\),就是胜利了,如果尾指针也是这样那么同上,最重要的是平局,那么如果\(a_{ra}\)<\(b_{rb}\),就让\(a_{ra}\)作为炮灰去浪费齐王的好马。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int a[514514],b[514514],ans,n,la,lb,ra,rb,t;
int main() {
scanf("%d",&n);
for (int i=1; i<=n; i++) scanf("%d",&b[i]);
for (int i=1; i<=n; i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
sort(b+1,b+n+1);
la=lb=1;
ra=rb=n;
for (int i=1; i<=n; i++) {
if (b[rb]>a[ra]) {ans++;rb--;ra--;}
else {if (b[rb]<a[ra]) {ans--;lb++;ra--;}
else {if (b[lb]>a[la]) {ans++;lb++;la++;}
else {if (b[lb]<a[ra]) {ans--;lb++;ra--;}
}
}
}
}
cout<<ans*200<<endl;
return 0;
}
附带提一下,楼上有大佬用\(dp\),但是\(dp\)的复杂度是\(O(n^2)\),但贪心是\(O(nlog^2n)\)的。如果多组数据或数据加强就过不去了,如这道题的加强版