描述
小A和小B決定利用假期外出旅行,他們將想去的城市從1到N編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市i 的海拔高度為Hi,城市i 和城市j 之間的距離d[i,j]恰好是這兩個城市海拔高度之差的絕對值,即d[i,j] = |Hi - Hj|。
旅行過程中,小A和小B輪流開車,第一天小A開車,之後每天輪換一次。他們計劃選擇一個城市S作為起點,一直向東行駛,並且最多行駛X公裡就結束旅行。小A和小B的駕駛風格不同,小B總是沿著前進方向選擇一個最近的城市作為目的地,而小A總是沿著前進方向選擇第二近的城市作為目的地(注意:本題中如果當前城市到兩個城市的距離相同,則認為離海拔低的那個城市更近)。如果其中任何一人無法按照自己的原則選擇目的城市,或者到達目的地會使行駛的總距離超出X公裡,他們就會結束旅行。
在啟程之前,小A想知道兩個問題:
1.對於一個給定的X=X0,從哪一個城市出發,小A開車行駛的路程總數與小B行駛的路程總數的比值最小(如果小B的行駛路程為0,此時的比值可視為無窮大,且兩個無窮大視為相等)。如果從多個城市出發,小A開車行駛的路程總數與小B行駛的路程總數的比值都最小,則輸出海拔最高的那個城市。
2. 對任意給定的X=Xi 和出發城市Si,小A開車行駛的路程總數以及小B行駛的路程總數。 格式 輸入格式
第一行包含一個整數N,表示城市的數目。
第二行有N個整數,每兩個整數之間用一個空格隔開,依次表示城市1到城市N的海拔高度,即H1,H2,……,Hn,且每個Hi 都是不同的。
第三行包含一個整數X0。
第四行為一個整數M,表示給定M組Si和Xi。
接下來的M行,每行包含2個整數Si 和Xi,表示從城市Si 出發,最多行駛Xi 公裡。 輸出格式
輸出共M+1行。
第一行包含一個整數S0,表示對於給定的X0,從編號為S0的城市出發,小A開車行駛
的路程總數與小B行駛的路程總數的比值最小。
接下來的M行,每行包含2個整數,之間用一個空格隔開,依次表示在給定的Si 和Xi 下小A行駛的裡程總數和小B行駛的裡程總數。 範例1 範例輸入
4 2 3 1 4 3 4 1 3 2 3 3 3 4 3
範例輸出
1 1 1 2 0 0 0 0 0
範例2 範例輸入
10 4 5 6 1 2 3 7 8 9 10 7 10 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 7 10 7
範例輸出
2 3 2 2 4 2 1 2 4 5 1 5 1 2 1 2 0 0 0 0 0
限制
每個測試點1s 提示
對於30%的資料,有1≤N≤20,1≤M≤20;
對於40%的資料,有1≤N≤100,1≤M≤100;
對於50%的資料,有1≤N≤100,1≤M≤1,000;
對於70%的資料,有1≤N≤1,000,1≤M≤10,000;
對於100%的資料,有1≤N≤100,000,1≤M≤10,000,-1,000,000,000≤Hi≤1,000,000,000,0≤X0≤1,000,000,000,1≤Si≤N,0≤Xi≤1,000,000,000,資料保證Hi 互不相同。 來源
Noip2012提高組複賽Day1T3
這個題 想到了類比。。。。
T3居然是類比。。。
其實70分感覺非常簡單
首先預先處理出每個點向後的最短 次短的目的地和距離
然後類比一下啦
。。。。。。。。
另外比值那個東西要開到19億才能70
一開始拙計開9億999 只有65 還不錯。。。
不用long long也可以70 = =
貼代碼吧
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int lim=1011;const int inf=1999999999;struct side{int x,y,h,w;}s[lim*lim];struct self{int first,nxt,fw,nw;}g[lim];int m,casenum,n,a,b,c,h[lim];int x,y,l,r,ans,ansh;double bizhi=0;inline int Abs(int i){return i<0?-i:i;}int cmp(side a1,side a2){return a1.w==a2.w?a1.h<a2.h:a1.w<a2.w;}void yuchuli(){ int a,b,c; for(a=1;a<=m;a++) for(b=a+1;b<=m;b++) { n++; s[n].x=a; s[n].y=b; s[n].h=h[b]; s[n].w=Abs(h[a]-h[b]); } sort(s+1,s+n+1,cmp); for(a=1;a<=n;a++) { int u=s[a].x; if(g[u].fw==0){g[u].first=s[a].y;g[u].fw=s[a].w;} else if(g[u].nw==0){g[u].nxt=s[a].y;g[u].nw=s[a].w;} //else if(g[u].fw>s[a].w) }}void work(int from,int dis,int now){ //cout<<"work("<<from<<","<<dis<<","<<now<<")"<<endl; if(now==1) { if(dis<g[from].nw)return; if(g[from].nxt==0)return; l+=g[from].nw; work(g[from].nxt,dis-g[from].nw,2); } else { if(dis<g[from].fw)return; if(g[from].first==0)return; r+=g[from].fw; work(g[from].first,dis-g[from].fw,1); }} int main(){ scanf("%d",&m); for(a=1;a<=m;a++)scanf("%d",&h[a]); yuchuli(); //for(a=1;a<=n;a++)cout<<s[a].x<<" "<<s[a].y<<" "<<s[a].h<<" "<<s[a].w<<endl; //for(a=1;a<=m;a++)cout<<"g["<<a<<"]="<<g[a].first<<" "<<g[a].fw<<" "<<g[a].nxt<<" "<<g[a].nw<<endl; scanf("%d",&y); bizhi=inf; for(a=1;a<=m;a++) { l=r=0; work(a,y,1); //From a Person 1 Length Y if(r==0&&h[a]>ansh&&bizhi>inf-1) { ansh=h[a]; ans=a; } if(r!=0&&(double)l/r<bizhi) { ansh=h[a]; ans=a; bizhi=(double)l/r; } //cout<<"a="<<a<<" ans="<<ans<<" bizhi="<<bizhi<<" l="<<l<<" r="<<r<<endl; } printf("%d\n",ans); scanf("%d",&casenum); while(casenum) { casenum--; scanf("%d%d",&x,&y); l=r=0; work(x,y,1); printf("%d %d\n",l,r); } return 0;}
AC做法
如果有時間的話 再研究下
NOIP RP++