JZOJ 4722. 跳楼机

Description

 
DJL为了避免成为一只咸鱼,来找srwudi学习压代码的技巧。
Srwudi的家是一幢h层的摩天大楼。由于前来学习的蒟蒻越来越多,srwudi改造了一个跳楼机,使得访客可以更方便的上楼。
经过改造,srwudi的跳楼机可以采用以下四种方式移动:
1、向上移动x层;
2、向上移动y层;
3、向上移动z层;
4、回到第一层。
一个月黑风高的大中午,DJL来到了srwudi的家,现在他在srwudi家的第一层,碰巧跳楼机也在第一层。DJL想知道,他可以乘坐跳楼机前往的楼层数。
 

Input

第一行一个整数h,表示摩天大楼的层数。
第二行三个正整数,分别表示题目中的x, y, z。

Output

一行一个整数,表示DJL可以到达的楼层数。
 

Sample Input

15
4 7 9

Sample Output

9
样例解释
可以到达的楼层有:1,5,8,9,10,12,13,14,15
 
做法:先考虑Hash,发现行不通,然后思考,处理出f[i]数组表示在不使用x的情况下达到的高度%x意义下等于i的最低高度。

那么如果到达了这个高度,就可以在这个基础上不断的跳x,达到i+kx的高度,这种高度对答案的贡献就是(h-f[i])/x+1。考虑

如何计算f,有两个明显的转移f[(i+y)%x] = f[i] + y, 对于z同理,于是这道题就被转变成最短路的模型,利用spfa求F[i]即可

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <queue>
 5 #define LL long long
 6 #define N 100007
 7 using namespace std;
 8 LL h,f[N],ans;
 9 int x,y,z,tot,ls[N];
10 struct edge{
11     int to,next,w;
12 }e[N*4];
13 queue<int> q;
14 bool v[N];
15 
16 void Add(int u,int v,int w){
17     e[++tot].to=v;
18     e[tot].w=w;
19     e[tot].next=ls[u];
20     ls[u]=tot;
21 }
22 
23 void Spfa(){
24     memset(f,0x3f3f3f3f,sizeof(f));
25     f[1%x]=1; v[1%x]=1; q.push(1%x);
26     for(;!q.empty();){
27         int now=q.front(); q.pop();
28         for(int i=ls[now];i;i=e[i].next){
29             int vis=e[i].to;
30             if(f[now]+e[i].w>=f[vis]) continue;
31             f[vis]=f[now]+e[i].w;
32             if(!v[vis]){
33                 v[vis]=1;
34                 q.push(vis);
35             }
36         }
37         v[now]=0;
38     }
39 }
40 
41 int main(){
42     scanf("%lld", &h);
43     scanf("%d%d%d",&x,&y,&z);
44     for(int i=0;i<x;i++)    Add(i,(i+y)%x,y),Add(i,(i+z)%x,z);
45     Spfa();
46     for(int i=0;i<x;i++)    if(f[i]<=h) ans+=(h-f[i])/(LL)x+1;
47     printf("%lld", ans);
48 }
View Code
原文地址:https://www.cnblogs.com/traveller-ly/p/9517746.html