POJ3539 Elevator 【同余类最短路】

题目描述:

电梯有n层,开始在1层,每次可以向上升a,b,c层,问可以到达的层数。
n<=1018,1<=a,b,c<=100000

题目分析:

把楼层对a取模,按余数分成a类。同一余数的楼层只要最低的那层可达,其它所有都可达。
所以只需要考虑上升b,c层,求出模a余i的可达的最低的楼层。
d i s [ i ] dis[i] dis[i]表示模a余i可达的最低的楼层,转移是显然的:
d i s [ i ] = min ⁡ ( d i s [ i ] , d i s [ ( i − b ) % a + b ] , d i s [ ( i − c ) % a + c ] ) dis[i]=\min(dis[i],dis[(i-b)\%a+b],dis[(i-c)\%a+c]) dis[i]=min(dis[i],dis[(ib)%a+b],dis[(ic)%a+c])
转移有环,把每个类看成一个点,跑最短路即可,这就是同余类最短路。

Code:

#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 100005
#define LL long long
using namespace std;
int a,b,c;
bool inq[maxn];
LL dis[maxn],n,ans;
queue<int>q;
inline void upd(int x,LL y){
	if(dis[x]>y){
		dis[x]=y;
		if(!inq[x]) inq[x]=1,q.push(x);
	}
}
void SPFA(){
	memset(dis,0x3f,sizeof dis);
	dis[1]=1,q.push(1);
	while(!q.empty()){
		int x=q.front();q.pop(),inq[x]=0;
		upd((x+b)%a,dis[x]+b),upd((x+c)%a,dis[x]+c);
	}
}
int main()
{
	freopen("elevator.in","r",stdin);
	freopen("elevator.out","w",stdout);
	scanf("%lld%d%d%d",&n,&a,&b,&c);
	if(a==1) return printf("%lld\n",n),0;
	SPFA();
	for(int i=0;i<a;i++) if(dis[i]<=n) ans+=(n-dis[i])/a+1;
	printf("%lld\n",ans); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值