2021牛客多校#9 J-Jam

本文分析了一道关于控制十字路口信号灯以解决交通拥堵问题的算法题目。通过理解题意,作者指出右转车辆不受限制,重点在于处理直行和左转车辆的冲突。通过构建图模型并进行分类讨论,提出了一种求解所需最短时间的策略,并给出了相应的复杂度分析和代码实现。
摘要由CSDN通过智能技术生成
原题链接
						https://ac.nowcoder.com/acm/contest/11260/J	

题目大意

你需要控制十字路口的信号灯。下图显示了右侧交通(RHT,即驾驶员保持在道路右侧)中十字路口的典型。在不考虑掉头的情况下,共有12种方向:N->E,N->S,N->W,E->S,E->W,E->N,S->W,S->E,W->N,W->E和W->S。
在这里插入图片描述
现在已经发生堵车,12个方向上形式的汽车数量已知,每辆车需要1秒通过十字路口,假设一辆汽车通过十字路口后不在出现,也不会出现新的汽车。

现在需要为每秒分配一个合适的交通信号灯,以尽快解决拥堵(所有汽车成功通过十字路口)。且确保汽车间不会发生碰撞。下图显示一个合法的方案:
在这里插入图片描述
下图是一个非法方案,图中两个标记处可能发生碰撞。但允许两辆车同时进入一条道路。
在这里插入图片描述
求让所有车都通过十字路口所需的最少时间。
每条道路最多有100辆车。

题解

根据题意,我们不难发现,计算时间时我们并不需要考虑右转的情况,因为右转无论如何都不会和别的方向来的车发生碰撞,所以我们只需让右转的灯保持常开,记录所有车道右转的车辆的数量的最大值并与不右转的车辆全部通过的时间进行比较即可。

所以我们得到以下路况:
在这里插入图片描述
然后我们将所有路口可能通过的车辆情况进行连边,得到下图:

整理后可得:
在这里插入图片描述
此时我们得到的红色边环的解决方案为:

接下里分类讨论:

  • d − a ≥ ( b − a ) + ( c − a ) d-a\ge (b-a)+(c-a) da(ba)+(ca)时,边权为 ( d − a ) + 2 × a (d-a)+2\times a (da)+2×a
  • d − a ≤ ( b − a ) + ( c − a ) d-a\le (b-a)+(c-a) da(ba)+(ca)时,边权为 ( b − a ) + ( c − a ) + 2 × a (b-a)+(c-a)+2\times a (ba)+(ca)+2×a

所以此时边权为 m a x ( a + d , b + c ) max(a+d,b+c) max(a+d,b+c)

接下来就是考虑蓝色边的方案,我们可以通过枚举所有方案的到最优解,但是直接暴力枚举的复杂度为 O ( 1 0 8 ) O(10^8) O(108),会TILE。我们可以将所有蓝色边删去一个固定值,得到至少一条为 0 0 0的边,然后算出剩下的边权。所以我们只需要枚举删去哪条边的值,然后计算剩下三条边的权值,最终与每个车道右转车辆最大值取较大值即可。
这时每次求值的复杂度为 O ( 4 × 1 0 6 ) O(4\times 10^6) O(4×106),题目给出的时间也很充足,所以成立。

参考代码

#include<bits/stdc++.h>
#define FOR(i,n,m) for(int i=n;i<=m;i++)
#define pb push_back
using namespace std;
int T,a[5],b[5],c[5],ans,sr,s[5];
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		int p;
		scanf("%d %d %d %d",&p,&a[1],&b[1],&c[1]);
		scanf("%d %d %d %d",&c[2],&p,&a[2],&b[2]);
		scanf("%d %d %d %d",&b[3],&c[3],&p,&a[3]);
		scanf("%d %d %d %d",&a[4],&b[4],&c[4],&p);
		sr=max(max(c[1],c[4]),max(c[2],c[3]));
		ans=0x3f3f3f3f;
		FOR(i,0,100)
			FOR(j,0,100)
				FOR(k,0,100)
				{
					s[0]=i,s[1]=j,s[2]=k;
					FOR(x,0,3)
					{
						int a0=0,b0=0,a1=0,b1=0,a2=0,b2=0,a3=0,b3=0;
						a0=max(a0,b[3]-s[(x+3)%4]),a2=max(a2,b[1]-s[(x+1)%4]);
						b0=max(b0,a[3]-s[x%4])    ,b2=max(b2,a[1]-s[(x+2)%4]);
						a1=max(a1,b[2]-s[x%4])    ,a3=max(a3,b[4]-s[(x+2)%4]);
						b1=max(b1,a[2]-s[(x+1)%4]),b3=max(b3,a[4]-s[(x+3)%4]);
						//强迫症犯了,不对齐看着不舒服
						ans=min(ans,max(a0+b2,a2+b0)+max(a1+b3,a3+b1)+i+j+k); 
					}
				}
		printf("%d\n",max(ans,sr));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值