1. 程式人生 > >[搬運] [貪心]NOIP2011 觀光公交

[搬運] [貪心]NOIP2011 觀光公交

end ber main endif bsp using .cn contain 即使

推薦這篇題解:http://www.cnblogs.com/Blacko/archive/2013/10/18/3376597.html

只不過這篇題解有一些細節沒有說清,但建議自己思考~

Codes:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #include<bits/stdc++.h> using
namespace std; typedef long long ll; const int N=1010,M=10010; int D[N]; ll up[N],leave[N],upt[N]; ll sum[N],f[N]; struct Passenger{ int s,e; ll t; }p[M]; ll endt[N]; int n,m,k; inline ll conc(bool spdup){ int nt,np; nt=np=0; ll eff=-0x7fffffff,idx=-1,ne; //計算endt for(int i=1;i<=n;i++){ endt[i]=max(endt[i-1],upt[i-1])+D[i-1]; }
//計算f for(int i=n-1;i>=1;i--)f[i]=(upt[i+1]>=endt[i+1]?1:f[i+1]+1); //計算eff for(int i=1;i<=n;i++){ if(!D[i])continue; ne=sum[f[i]+i]-sum[i]; if(ne>eff)eff=ne,idx=i; } if(spdup)D[idx]--; else{ nt=0; for(int i=1;i<=m;i++) nt+=endt[p[i].e]-p[i].t;
return nt; } return 0; } int main(){ #ifdef LOCAL freopen("bus.in","r",stdin); freopen("bus.out","w",stdout); #endif scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n-1;i++){ scanf("%d",&D[i]); } ll t,u,l; for(int i=1;i<=m;i++){ scanf("%lld%lld%lld",&t,&u,&l); upt[u]=max(upt[u],t); up[u]++; leave[l]++; p[i].s=u,p[i].e=l,p[i].t=t; } //計算sum for(int i=1;i<=n;i++)sum[i]=sum[i-1]+leave[i]; for(int i=1;i<=k;i++){ conc(true); } printf("%lld\n",conc(false)); return 0; }

Solution:

兩點需要註意的地方(按上方題解提供的數組含義來寫):

1.f[i]的推導。我一開始以為是若last[i+1]>time[i+1]則為0,得到的結果比答案大一點點……然後稍微魔改成了last[i+1]>=time[i+1]則為1,就tm對了……想了一下,可能是因為即使下一個站需要等待,這一個站至少能影響到第二個站;以及為什麽是last[i+1]>=time[i+1]而非last[i+1]>time[i+1]——當last[i+1]==time[i+1]時,此時time[i+1]再減少,下一個站仍然會變成需要等待,所以也對後方沒有影響,所以last[i+1]>=time[i+1]才是正確的範圍。

2.當一條邊已經被加速到0時,不能再加速。

其它看上面的題解和我的代碼吧2333

[搬運] [貪心]NOIP2011 觀光公交