题意:环形跑道上有N个加油站,编号为1~N。第 i 个加油站可以加油Ai加仑,从加油站 i 开到下一站需要Bi加仑汽油。问可作为起点走完一圈后回到起点的最小加油站编号。
解法:我们把每个加油站的Ai,Bi合并,把Ai-Bi看成N个点的权Ci,表示经过 i 的剩余油量。可知可通过第 i 个加油站就是sum{}+Ci>=0,sum{}表示从起点开到 i 之前剩余的油量,sum{}>=0。因此,若sum{}+Ci<0,那么从这时枚举的起点到 i 之间的所有点都不能作为起点,因为这时的sum{}已经是以他们为起点所能达到的最大值了,不可能有更多的油量剩余,一定不能通过点 i。便枚举 i+1 为起点,继续判断。
P.S.由于是环,判断走完一圈也有点麻烦,大家要小心。我觉得我打的虽然比较短,但也不是很优美。= =
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 #include<iostream> 6 #include<queue> 7 using namespace std; 8 const int N=100010; 9 10 int n; 11 int a[N],b[N]; 12 int mmax(int x,int y) {return x>y?x:y;} 13 int check(int x) 14 { 15 int h=0,t=x; 16 bool tf=true; 17 while(1) 18 { 19 if (t==x&&!tf) return -1; 20 h+=a[t]-b[t]; 21 if (h<0) return t; 22 tf=false; 23 t=(t+1)%n; 24 } 25 } 26 int main() 27 { 28 int T; 29 scanf("%d",&T); 30 for (int kase=1;kase<=T;kase++) 31 { 32 scanf("%d",&n); 33 for (int i=0;i<n;i++) scanf("%d",&a[i]); 34 for (int i=0;i<n;i++) scanf("%d",&b[i]); 35 int ans=n,x=0,tmp,mx=-1; 36 while (1) 37 { 38 if (x<=mx) break; 39 tmp=check(x),mx=mmax(mx,x); 40 if (tmp==-1) {ans=x;break;} 41 else x=tmp+1; 42 } 43 if (ans!=n) printf("Case %d: Possible from station %d ",kase,ans+1); 44 else printf("Case %d: Not possible ",kase); 45 } 46 return 0; 47 }