1. 程式人生 > >洛谷 P1315 觀光公交 —— 貪心

洛谷 P1315 觀光公交 —— 貪心

tdi pri org font ring 重新 貪心 \n show

題目:https://www.luogu.org/problemnew/show/P1315

問題是想不明白改動一條邊會對後面造成怎樣的影響;

實際上影響的會是一段,當某個車站出發時間受其來人牽制時,前面的時間減小就不會起到效果;

所以對於每個車站,求一個 g[i] 表示最遠能影響到哪個車站,則修改 i 後面那條邊,所有到達點在 i ~ g[i] 的人的時間都縮短1;

每次找一個縮短最大的邊,然後重新計算每個車站的實際到達時間和 g[i],其實就是貪心。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include
<algorithm> using namespace std; int const xn=1005,xm=1e4+5; int n,m,K,d[xn],f[xn],t[xm],tim[xn],ans,st[xm],ed[xm],s[xn],g[xn]; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=0; ch=getchar();} while(ch>=0&&ch<=9)ret=(ret<<3)+(ret<<1
)+ch-0,ch=getchar(); return f?ret:-ret; } int main() { n=rd(); m=rd(); K=rd(); for(int i=1;i<n;i++)d[i]=rd(); for(int i=1;i<=m;i++) { t[i]=rd(); st[i]=rd(); ed[i]=rd(); f[st[i]]=max(f[st[i]],t[i]); s[ed[i]]++; } tim[1]=0; for(int i=2;i<=n;i++)tim[i]=max(tim[i-1
],f[i-1])+d[i-1],s[i]+=s[i-1]; for(int i=1;i<=m;i++)ans+=tim[ed[i]]-t[i]; while(K) { g[n]=n; for(int i=n-1;i;i--) { if(/*tim[i]+d[i]*/tim[i+1]>f[i+1])g[i]=g[i+1]; else g[i]=i+1; } int mx=0,c=0;//0 而非 -1 防止 K 有余而 d<0 時減了 -1 for(int i=1;i<n;i++) if(s[g[i]]-s[i]>mx&&d[i]>0)mx=s[g[i]]-s[i],c=i;//>0 ans-=mx; d[c]--; for(int i=2;i<=n;i++)tim[i]=max(tim[i-1],f[i-1])+d[i-1]; K--; } printf("%d\n",ans); return 0; }

洛谷 P1315 觀光公交 —— 貪心