P3403 跳楼机

跳楼机

https://www.luogu.org/problemnew/show/P3403 (题目链接)

题目

Srwudi的家是一幢h层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi改造了一个跳楼机,使得访客可以更方便的上楼。

经过改造,srwudi的跳楼机可以采用以下四种方式移动:

1.向上移动x层;

2.向上移动y层;

3.向上移动z层;

4.回到第一层。

一个月黑风高的大中午,DJL来到了srwudi的家,现在他在srwudi家的第一层,碰巧跳楼机也在第一层。DJL想知道,他可以乘坐跳楼机前往的楼层数。

简化版题目:给你一个数字h,三个数字x,y,z。求出三个数字组合出的小于等于h的数字种类。

输入输出格式

输入格式:
第一行一个整数h,表示摩天大楼的层数。

第二行三个正整数,分别表示题目中的x, y, z。

输出格式:
一行一个整数,表示DJL可以到达的楼层数。

输入输出样例
输入样例
#1:
15
4 7 9
输出样例
#1:
9

输入样例
#2:
33333333333
99005 99002 100000
输出样例
#2:
33302114671

思路

首先因为三个数字的不太好思考,所以可以先考虑两个数字的结果。
两个数字(x,y)
1.可以把h分成两个部分(一部分是x,一部分是y),在这里姑且用x为填充物

2.可以定义一个d[i]数组记录由y组成的数字在mod x的情况下余数为i的最小值(这里设置为最小值是为了避免d数组的重复)

3.统计数字数。ans+=(h-d[i])/x+1【/x是找到可以填充多少个x,+1是因为可能会有x不填充的情况】

之后,考虑 三个数字(x,y,z) 的情况的情况:

1.【同上】可以把h分成两个部分(一部分是x,一部分是y,z),在这里姑且用x为填充物

【划重点】 2.d[i]数组的意义同上,但是这个时候要如何找到两个数字(y,z)在mod x时的最小的余数??而且还要保证这个y,z组合的 任意性随机性 ,而且要保证d[i]是最小的(这里需要冷静思考。)【如果d[i]是最小的的话就不会有重复的情况出现】

此时,可以考虑最短路了,说实话,我没想到 ,用y,z建边权,以i为下标,此时去跑最短路!!【正解的精简干练??】
3.统计数字数。同上。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mm=1e5+100;
ll h,x,y,z,ans;
int num=0;
ll d[mm];
bool v[mm];

queue<int> q;

struct edge
{
	int to,nex;
	ll ver;
}e[2*mm];
int last[mm];

void add(int x,int y,ll c)
{
	e[++num].to=y; e[num].ver=c;
	e[num].nex=last[x]; last[x]=num;
}

void spfa()//求单源最短路径,参考思路上的内容
{
	memset(d,0x3f3f3f3f,sizeof(d));
	memset(v,0,sizeof(v));
	d[0]=1;v[0]=1;
	q.push(0);
	while(q.size())
	{
		int xx=q.front(); q.pop();
		v[xx]=0;
		for(int i=last[xx];i;i=e[i].nex)
		{
			int y=e[i].to;
			ll z=e[i].ver;
			if(d[y]>d[xx]+z)
			{
				d[y]=d[xx]+z;
				if(!v[y])
					q.push(y),v[y]=1;
			}
		}
	}
}

int main()
{
//	freopen("srwudi.in","r",stdin);
//	freopen("srwudi.out","w",stdout);
	cin>>h>>x>>y>>z;//以x为最后的填充对象
	num=1;
	for(int i=0;i<x;i++)//建边
	{
		add(i,(i+y)%x,y);
		add(i,(i+z)%x,z);
	}
	spfa();
	for(int i=0;i<x;i++)
		if(d[i]<=h)
			ans+=(h-d[i])/x+1;//还有可能就是(h-d[i])不被x填充的情况,所以在这里要+1
	cout<<ans<<endl;
	return 0;
}

完……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值