您的位置:首页 > 其它

uva 11093 Just Finish it up

2018-02-10 15:46 337 查看
原题:

Along a circular track, there are N gas stations, which are numbered clockwise from 1 up to N. At

station i, there are p i gallons of petrol available. To race from station i to its clockwise neighbor one

need q i gallons of petrol. Consider a race where a car will start the race with an empty fuel tank. Your

task is to find whether the car can complete the race from any of the stations or not. If it can then

mention the smallest possible station i from which the lap can be completed.

Input

First line of the input contains one integer T the number of test cases. Each test case will start with a

line containing one integer N, which denotes the number of gas stations. In the next few lines contain

2 ∗ N integers. First N integers denote the values of p i s (petrol available at station i), subsequent N

integers denote the value of q i s (amount of patrol needed to go to the next station in the clockwise

direction).

Output

For each test case, output the case number in the format “Case c:” , where c is the case number starting

form 1. Then display whether it is possible to complete a lap by a car with an empty tank or not. If it

is not possible to complete the lap then display “Not possible”. If possible, then display “Possible

from station X”, where X is the first possible station from which the car can complete the lap.

Constraints

• T < 25

• N < 100001

Sample Input

2

5

1 1 1 1 1

1 1 2 1 1

7

1 1 1 10 1 1 1

2 2 2 2 2 2 2

Sample Output

Case 1: Not possible

Case 2: Possible from station 4

中文:

有一辆车在一个个环形跑道跑,上面有n个加油站,你可以任意选一个加油站作为起点,要求能跑一圈回到起点。假设车的油箱大小无限大,让你选择一个编号最小的、而且满足条件的起点。

首先给定n个数表示n个加油站有多少油,下一行给定n个数,表示从当前加油站到下一个加油站消耗多少油。

注意,本题只考虑从前往后的单方向!-_-

代码:

#include<bits/stdc++.h>
using namespace std;

int t, n, T=1;
int a[100001];
int main()
{
ios::sync_with_stdio(false);
cin >> t;
while (t--)
{
cin >> n;
memset(a, 0, sizeof(a));
int tmp;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}

for (int i = 1; i <= n; i++)
{
cin >> tmp;
a[i] -= tmp;
}

tmp = 0;
for (int i = 1; i <= n; i++)//如果总和小于0,那么不可能成功
tmp += a[i];
cout<<"Case "<<T++<<": ";

if(n==1)//只有一个加油站的情况
{
if(a[1]>=0)
{
cout << "Possible from station " <<1<<endl;
}
else
{
cout << "Not possible" << endl;
}
continue;
}
if (tmp < 0)
{
cout << "Not possible" << endl;
continue;
}
int ind, flag = 1, flag2 = 1;//s表示选择起点,ind枚举从当前加油站往后走
tmp = 0;    //tmp为累加往后走时的油量
int s = 1;
ind = s;
while (a[s]<0)//选取的起点一定是有当年的加油量大于等于到下一个加油站的路程
{
s++;
ind = s;
}
while (true)
{
if (ind > n)
{
ind = 1;

flag2 = 0;
}
tmp += a[ind];
while (tmp<0)
{
s++;
if (s == ind)
{
while (a[s]<0)
{
s++;
ind = s;
}
tmp = a[s];
break;
}
if (s == n)
{
flag = 0;
break;
}
tmp -= a[s-1];
}

if (flag == 0||(ind+1)%n==s&&tmp>=0)
break;
ind++;
if (ind == s&&flag2 == 0)
break;
}
cout << "Possible from station " <<s<<endl;

}
return 0;
}


解答:

紫书上面的例题

注意此题只能单方向走,不能反向走圈。

此题可以用到前面提到的滑动窗口的知识,首先把所有a[i]值变成第i加油站的油量减去从i到i+1个加油站的消耗油量,

记录在a[i]当中。

如果问题有解,那么a[i]的累加和一定是大于等于0的

个首先设置当前起始点s,然后从s往前走,以ind值遍历s后面的剩余油量a[i],并以tmp变量累加a[i],如果出现tmp<0,那么一定是从s点到ind点不能走通,那么起始点向前移动,同时变化tmp值,变化的方法为tmp-=a[s],因为以s为起点到ind之间这个窗口[s,ind][s,ind]的油量值是tmp,现在窗口左侧的s值要向前移动,所以要把窗口中左区间的加油站剩余值a[s]减掉即可。

最后输出结果即可。。

书中的做法要简单不少,原话大意为:考虑第i号交友站,判断是否有解,如果有输出,如果没有,说明途中遇到加油站p,从p到p+1没油了。那么,以i+1,i+2,i+3….p为起点也不是解,原因是,如果i能作为起点,i点的油量减去到i+1点的消耗值一定大于等于0的一个数,设为从i点走到i+1点后剩余的油量为t(t>=0)。如果从i点到p没油了,那么从i+1点到p点,相当于从i点到p点减去s,那剩下的油量就更少了。所以,如果i到p如果无解,直接跳到以p+1为起点进行判断即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: