Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
一个很巧妙的方法(附PASCAL程序)首先,我们可以有一个很朴素的想法,就是依次枚举读入的n*m个东西的带宽为B,这样就只要使P尽量小就行了。而要使P尽量小,就要在每一类设备中选带宽大于等于B,而P又最小的那个。然而这个算法的复杂度是O(N²*M²),显然会超时。于是我们就要进行优化。 我们可以将每一类设备分别按带宽由小到大和价格由小到大排序的到两个数组F和S。然后按F数组来枚举n*m个东西(也就是带宽有小到大),按S数组来寻找带宽大于等于B,而P又最小的那个。由于S数组中价格递增,所以只需顺序找到第一个带宽大于等于B的就行了。但这个算法仍可能超时。我们发现由于F数组是按带宽递增的,所以我们在S数组中寻找时可以从上次找到的位置继续寻找,于是只要用一个Q数组来记录每次寻找到的位置即可。这样程序的复杂度就降为O(n²m),就可以AC了。 Code: type node=record b,p:array[1..100] of longint; m:longint; end; var s,f:array[1..100] of node; t,n:longint; procedure init; var i,j:longint; begin fillchar(s,sizeof(s),0); fillchar(f,sizeof(f),0); readln(n); for i:=1 to n do begin read(s[i].m); for j:=1 to s[i].m do read(s[i].b[j],s[i].p[j]); readln; end; end; procedure qsort1(num,l,r:longint); var i,j,x,temp:longint; begin i:=l; j:=r; x:=f[num].b[(l+r) shr 1]; while i<j do begin while f[num].b[i]<x do inc(i); while x<f[num].b[j] do dec(j); if i<=j then begin temp:=f[num].b[i]; f[num].b[i]:=f[num].b[j]; f[num].b[j]:=temp; temp:=f[num].p[i]; f[num].p[i]:=f[num].p[j]; f[num].p[j]:=temp; inc(i); dec(j); end; end; if l<j then qsort1(num,l,j); if i<r then qsort1(num,i,r); end; procedure qsort2(num,l,r:longint); var i,j,x,temp:longint; begin i:=l; j:=r; x:=s[num].p[(l+r) shr 1]; while i<j do begin while s[num].p[i]<x do inc(i); while x<s[num].p[j] do dec(j); if i<=j then begin temp:=s[num].b[i]; s[num].b[i]:=s[num].b[j]; s[num].b[j]:=temp; temp:=s[num].p[i]; s[num].p[i]:=s[num].p[j]; s[num].p[j]:=temp; inc(i); dec(j); end; end; if l<j then qsort2(num,l,j); if i<r then qsort2(num,i,r); end; procedure work; var q:array[1..100] of longint; i,j,k,sum:longint; ans:double; flag:boolean; begin for i:=1 to n do begin f[i]:=s[i]; qsort1(i,1,f[i].m); qsort2(i,1,s[i].m); end; ans:=-1000000000; for i:=1 to n do begin for j:=1 to n do q[j]:=1; for j:=1 to f[i].m do begin sum:=f[i].p[j]; flag:=true; for k:=1 to n do if i<>k then begin while (s[k].b[q[k]]<f[i].b[j]) and (q[k]<=s[k].m) do inc(q[k]); if q[k]>s[k].m then begin flag:=false; break; end; sum:=sum+s[k].p[q[k]]; end; if not flag then break; if flag then if f[i].b[j]/sum>ans then ans:=f[i].b[j]/sum; end; end; writeln(ans:0:3); end; begin read(t); while t>0 do begin t:=t-1; init; work; end; end. Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator