最近有点不太顺,用python重写了不少uva的题目,不料都都TLE了。尝试改进了算法,C++版本的程序效率倒确实有了提升,但是python版本的还是TLE。问题肯定出在自身,毕竟还是有不少人用python代码AC了的。不过自身能力有限,目前而言没有啥办法可以提高python版本的代码效率了,所以想着还是先记录下来,万一哪天自己灵感来了,可以对比参考;亦或者哪位python大神看到了,可以给我提点提点。
言归正传。题意是说你中意的足球队参加一项慈善足球赛。因为是慈善赛,所以比赛结束之后,可以通过买球的方式,来改变最终比赛的结果。你中意的球队一共踢了N场球赛(1<=N<=100000),最多可以购买G个球(0<=G<=1000000),假设其他球队不买球的前提下,请问这种情况下,你中意的球队最多可以获得多少分。(足球比赛,赢一场得3分,平一场得1分,输一场不得分)
尽量用最少的球获取最多的分数,这个应该说就是贪心策略。而且思路也比较简单,按顺序:
- 赢了的比赛,直接每场3分;
- 每一个平局的比赛,只需要用1个球就可以使球队从原来的1分变成3分
- 输了的比赛,就要以净胜球从大到小排序(因为此时净胜球为负),到时候一场一场地比,如果G还有剩余,就比较G与净胜球x关系,G+x >0,那就可以使球队+3分; G+x == 0,那就可以使球队+1分,如果G+x < 0,算法结束。
以下是C++版本,AC的代码
#include <iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ZANGFONG
const int maxn = 100010;
int game[maxn];
int main()
{
#ifdef ZANGFONG
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // ZANGFONG
int N,G,i,a,b,score;
while(scanf("%d%d\n",&N,&G)!= EOF)
{
int cnt = 0;
int gwin = 0;
int gtie = 0;
for(i = 0; i < N; i++)
{
scanf("%d%d\n",&a,&b);
//game[i] = a - b;
if(a>b) gwin++;
else if(a==b) gtie++;
else game[cnt++] = b - a;
}
score = gwin * 3;
if(gtie >= G)
{
score += G * 2 + gtie;
}
else
{
score += gtie * 3;
G -= gtie;
sort(game,game+cnt);
for(i = 0; i < cnt; i++)
{
if(G - game[i] > 0)
{
G -= game[i] + 1;
score += 3;
}
else if(G - game[i] == 0)
{
score += 1;
break;
}
else break;
}
}
printf("%d\n",score);
}
return 0;
}
以下为python版本的代码,思路同C++的代码一样,但还是TLE了。这里先做记录,以后再来修改
while True:
try:
N,G = map(int,input().split())
except Exception as e:
break
game = [0 for _ in range(100001)]
gwin = 0
gtie = 0
cnt = 0
for i in range(N):
S,R = map(int,input().split())
if S - R > 0:
gwin += 1
elif S - R == 0:
gtie += 1
else:
game[cnt] = R-S
cnt += 1
score = gwin * 3
if gtie >= G:
score += G * 2 + gtie
else:
score += gtie * 3
G -= gtie
game.sort(reverse=True)
while cnt > 0:
if G - game[cnt-1] > 0:
G -= game[cnt-1] + 1
score += 3
cnt -= 1
elif G - game[cnt-1] == 0:
score += 1
break
else:
break
print(score)