1. 程式人生 > >LOJ#539. 「LibreOJ NOIP Round #1」旅遊路線

LOJ#539. 「LibreOJ NOIP Round #1」旅遊路線

efi 最小花費 return print def hide void struct amp

n<=100,m<=1000的圖,在此圖上用油箱容量C<=1e5的車來旅行,旅行時,走一條邊會耗一單偉油,在點i時,若油量<ci,則可以把油以pi的價格補到ci,pi<=n*n,ci<=1e5,現T<=1e5個詢問:從Ai出發,帶Yi<=n*n塊錢走不少於Si<=1e9的路程,問最多剩多少錢。

方法一:其實就是問從某個點出發,走路程Si,問最少花費。F(i,j,k)--從i出發,剩下j的油,走路程k最小花費,決策一下在i要不要加油即可。

方法二:走路程Si問最小花費-->花費q問最長路程。F(i,j,q)--從i出發剩j的油,用q塊錢最長路程,決策一下要不要在i加油即可。

方法三:整個路程其實就是由幾個加油處為中轉點拼起來的,因此只用加油處的狀態就可以勾勒整個過程,而加油處加完油後,油箱狀態和之前沒關系,可以省掉。F(i,q)--從i出發用q塊錢最長路程,F(i,q)=max(F(j,q-pi)+G(i,j)),G(i,j)表示從i開始,到j,經過不超過min(ci,C)條路的最長路。

G(i,j)的計算可以用倍增:W(i,j,k)表示i到j經過不超過2^k步的最長路程,用W來拼湊G。

最後詢問時,在F(Ai)數組裏二分找F(Ai,j)>=Si的最小的j,得答案。

有點復雜。。

技術分享
 1 #include<stdio.h>
 2 #include<string
.h> 3 #include<stdlib.h> 4 #include<math.h> 5 #include<algorithm> 6 //#include<iostream> 7 using namespace std; 8 9 bool isdigit(char c) {return c>=0 && c<=9;} 10 int qread() 11 { 12 char c;int s=0,t=1;while (!isdigit(c=getchar())) (c==- && (t=-1
)); 13 do s=s*10+c-0; while (isdigit(c=getchar())); return s*t; 14 } 15 int n,m,C,T; 16 #define maxn 111 17 #define maxm 2017 18 struct Edge{int to,v,next;}edge[maxm];int first[maxn],le=2; 19 void in(int x,int y,int v) {Edge &e=edge[le];e.to=y;e.v=v;e.next=first[x];first[x]=le++;} 20 21 #define LL long long 22 LL f[maxn][maxn*maxn],g[maxn][maxn],tmp[maxn][maxn],w[maxn][maxn][22],c[maxn],p[maxn]; 23 const LL inf=1e16; 24 void prebz() 25 { 26 for (int i=1;i<=n;i++) 27 for (int j=1;j<=n;j++) 28 w[i][j][0]=-inf; 29 for (int i=1;i<=n;i++) 30 { 31 w[i][i][0]=0; 32 for (int j=first[i];j;j=edge[j].next) 33 { 34 const Edge &e=edge[j]; 35 w[i][e.to][0]=e.v; 36 } 37 } 38 for (int k=1;k<=18;k++) 39 for (int i=1;i<=n;i++) 40 for (int j=1;j<=n;j++) 41 { 42 w[i][j][k]=-inf; 43 for (int x=1;x<=n;x++) 44 w[i][j][k]=max(w[i][j][k],w[i][x][k-1]+w[x][j][k-1]); 45 } 46 for (int i=1;i<=n;i++) 47 { 48 int o=min(c[i],1ll*C); 49 for (int j=1;j<=n;j++) g[i][j]=-inf; 50 g[i][i]=0; 51 for (int k=18;k>=0;k--) if (o&(1<<k)) 52 { 53 for (int j=1;j<=n;j++) tmp[i][j]=-inf; 54 for (int j=1;j<=n;j++) 55 for (int x=1;x<=n;x++) 56 tmp[i][j]=max(tmp[i][j],g[i][x]+w[x][j][k]); 57 for (int j=1;j<=n;j++) g[i][j]=tmp[i][j]; 58 } 59 } 60 } 61 62 void predp() 63 { 64 for (int j=0;j<=n*n;j++) 65 for (int i=1;i<=n;i++) 66 { 67 f[i][j]=0; 68 if (j>=p[i]) for (int x=1;x<=n;x++) f[i][j]=max(f[i][j],f[x][j-p[i]]+g[i][x]); 69 } 70 } 71 72 void init() 73 { 74 n=qread(),m=qread(),C=qread(),T=qread(); 75 for (int i=1;i<=n;i++) p[i]=qread(),c[i]=qread(); 76 for (int i=1,x,y,z;i<=m;i++) 77 { 78 x=qread(),y=qread(),z=qread(); 79 in(x,y,z); 80 } 81 } 82 83 int main() 84 { 85 init(); 86 prebz(); 87 predp(); 88 while (T--) 89 { 90 int x=qread(),y=qread(),z=qread(); 91 int t=lower_bound(f[x]+1,f[x]+1+n*n,z)-f[x]; 92 if (t<=y) printf("%d\n",y-t); 93 else puts("-1"); 94 } 95 return 0; 96 }
View Code

LOJ#539. 「LibreOJ NOIP Round #1」旅遊路線