UVA 11093 Just finish it up n个点循环问题

探讨了一个经典的算法问题:在形成闭环的加油站网络中,找出能够完成环形路径的最小起点位置。通过模拟策略,判断从哪个加油站出发可以确保有足够的油量返回起点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定n个加油站,形成一个环,每个加油站有一些油,从一个加油站行驶到另一个加油站需要消耗一些油,问最小可以从哪个点出发使得能够回到出发点;
这是一道模拟,首先模拟第一个点,如果从P点不能到P+1点(假设2<P<n),那么第一个点到第P个点一定都不是问题的解;因为如果从第一个点出发,能够到达第二个点,那么在第二个点未加油时油量是大于等于0的,而从第一个点出发到不了P点,以此类推,从第二个点,从第三个点,出发到达P点的油量一定小于等于从第一个点到达P点的油量,而从第一个点不能到达P+1,所以从2~P都不能到达P+1;所以如果模拟1不行,就再模拟P+1;先用sum保存一个加油站的油量,然后计算sum - A[i][1]是否大于0,如果是,就继续模拟,但需要特判一下i;如果i == n; i = 1;else i++; 就是要形成环;如果否,就用一个数组记录下一个要模拟的的点,即i+1;if(k[cur]- k[cur-1]<= 0)证明已经模拟过一圈了,并且都不符合,这时就break;还有一种判断就是当i == n的时候断了,这时说明下一次要模拟第一个点,证明一定是模拟了超过一圈了,这时直接break就行,不直接break也可以;如果还能继续模拟,要令sum = 0,重新开始,模拟P+1;出了判断后要记得给sum加上到达油站的油;循环条件是1就可以;反正最后会break;
1、还有一个问题,由于开始令k[cur] = i;而当进入循环时会判断k[cur]是否等于i;如果是,就有解,那么怎么规避呢,设一个st = 0;然后在判断是加上&& st;这样在判断完后如果i == k[cur] && !st; st = 1;这样就能规避第一次就相等的错误;然后如果模拟到sum小于0不符合了,也要再令st = 0;重新开始;
2、还有一个问题,就是如何判断已经跑了一圈了但是还没找到解的问题,因为开了一个数组来记录模拟的位置,如果没有模拟完一圈那么这时k[cur] - k[cur-1]一定是大于0的,因为是从1开始模拟,模拟到n;而如果小于等于0,就证明了已经跑完了一圈,还没找到答案,这时就要break;
3、还有一个问题,如何判断break之后是否找到了答案呢?设一个ok = 0;如果找到答案,ok = 1;否则ok一直为0;如果ok,就证明找到,否则,就没找到;
4、小问题,不用初始化k[0]为0,虽然从1开始记录,但不会出现k[1] - k[0] <= 0的情况;因为k[0]一直为0;
ok了

#include<iostream>
#include<cstring>
#define ll long long
using namespace std;

const int maxn = 1e5+10;
ll A[maxn][2], k[maxn];

int main()
{
	int T;
	scanf("%d",&T);
	int ans;
	ll sum;
	int cnt = 1;
	while(T--)
	{
		sum = 0;
		int n;
		scanf("%d",&n);
		for(int i = 1; i <= n; i++)
			scanf("%lld",&A[i][0]);
		for(int i = 1; i <= n; i++)
			scanf("%lld",&A[i][1]);
		int cur = 1;
		int ok = 0;
		int i = 1;
		k[1] = 1;
		k[0] = 0;
		int st = 0;
		sum += A[i][0];
		while(sum >= 0)
		{
			if(sum - A[i][1] >= 0){
				sum -= A[i][1];
				if(i == k[cur] && st){
					ok = 1;
					st = 0;
					break;
				}
				if(i == k[cur] && !st) st = 1;
				if(i == n) i = 1;
				else i++;
			}
			else{
				if(i == n) i = 1;
				else i++;
				sum = 0;
				k[++cur] = i;
				st = 0;
				if(k[cur] - k[cur-1]<= 0){
					break;
				}
			}
			sum += A[i][0];
		}
		printf("Case %d: ",cnt++);
		if(ok) printf("Possible from station %d\n",k[cur]);
		else printf("Not possible\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值