算是一道思维题吧,没有什么算法在里面。
之前想的是,能走的话就尽量走远,走过去开灯然后再回去关灯,然后再走,每一段路要走3次。
然而,“能走的话就尽量走远”只是yy的一个贪心,没有任何依据。假设在中间找一个过渡点的话,路程应该是长这个样子的:
总路程还是3倍距离,没有改变诶。
所以只要你认认真真地,正正常常地走路,不绕圈圈,所走的路程都是3倍距离。
所以只需要判断能不能走到就可以了。
既然如此,那就可以随便开灯了(大雾)
(没有开玩笑啊)是真的可以随便开灯了,因为只是要判断能否走到,就用不着节约了。
从左走到右的时候,依次开灯,每次开灯之后要保证至少走到下一个点
回去的时候不用管
再一次从左走到右关灯,这一次走的时候依靠的是前面没有被关的灯光
前面延伸到左边最远的灯光要保证自己所在的位置有灯
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<string> 5 #include<queue> 6 #include<algorithm> 7 #include<vector> 8 #include<cstdlib> 9 using namespace std; 10 #define N 300005 11 #define ll long long 12 #define INF 0x3f3f3f3f 13 int n; 14 int p[N],r[N]; 15 /* 16 从左走到右的时候,依次开灯,每次开灯之后要保证至少走到下一个点 17 回去的时候不用管 18 再一次从左走到右关灯,这一次走的时候依靠的是前面没有被关的灯光 19 前面延伸到左边最远的灯光要保证自己所在的位置有灯 20 */ 21 int main() 22 { 23 scanf("%d",&n); 24 for(int i=1;i<=n;i++) 25 scanf("%d %d",&p[i],&r[i]); 26 int far=p[1];//能够延伸到右边最远的灯光坐标 保证能够走到终点 27 for(int i=2;i<=n;i++) 28 { 29 far=max(far,p[i-1]+r[i-1]); 30 if(far<p[i]) 31 { 32 puts("-1"); 33 return 0; 34 } 35 } 36 far=p[n];//能够延伸到左边最远的灯光坐标 保证能够关灯 37 for(int i=n;i>=2;i--) 38 { 39 far=min(far,p[i]-r[i]); 40 if(far>p[i-1]) 41 { 42 puts("-1"); 43 return 0; 44 } 45 } 46 printf("%lld ",(p[n]-p[1])*3ll); 47 return 0; 48 }