poj 3539 Elevator——同余类bfs

题目:http://poj.org/problem?id=3539

考虑把层数分为模a剩余系。同类内可通过+若干个a走到。

不同类之间需要通过+b、+c来走到。

需要求出每一类中最小的能走到的。即最短路。

注意memset成0x3f!不要直接memset成1!

  仔细一看,long long下赋1是17位,赋0x3f是19位。而h是18位。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
const int N=1e5+5;
ll h,dis[N],ans;
int a,b,c,head[N],xnt;
bool vis[N];
struct Ed{
  int next,to,w;
  Ed(int n=0,int t=0,int z=0):next(n),to(t),w(z) {}
}ed[N<<1];
void dj()
{
  memset(dis,0x3f,sizeof dis);dis[1%a]=1;//%a //0x3f
  priority_queue<pair<ll,int> > q;
  q.push(make_pair(-1,1%a));
  while(q.size())
    {
      int k=q.top().second;q.pop();
      while(q.size()&&vis[k])k=q.top().second,q.pop();
      if(vis[k])break;vis[k]=1;
      for(int i=head[k],v;i;i=ed[i].next)
    if(dis[k]+ed[i].w<dis[v=ed[i].to])
      {
        dis[v]=dis[k]+ed[i].w;q.push(make_pair(-dis[v],v));
      }
    }
}
int main()
{
  scanf("%lld%d%d%d",&h,&a,&b,&c);
  for(int i=0;i<a;i++)
    {
      ed[++xnt]=Ed(head[i],(i+b)%a,b);head[i]=xnt;
      ed[++xnt]=Ed(head[i],(i+c)%a,c);head[i]=xnt;
    }
  dj();
  for(int i=0;i<a;i++)if(dis[i]<=h)ans+=(h-dis[i])/a+1;//<=h
  printf("%lld",ans);
  return 0;
}

dj

再来个跑得快的(spfa)。

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e5+5;
ll ans,h,dis[N];
int a,b,c,q[N<<4],hd,tl;
bool vis[N];
int main()
{
  scanf("%lld%d%d%d",&h,&a,&b,&c);
  if(a<b)swap(a,b);if(a<c)swap(a,c);
  memset(dis,0x3f,sizeof dis);dis[1%a]=1;
  hd=1;q[++tl]=1;vis[1%a]=1;
  while(hd<=tl)
    {
      int k=q[hd++];vis[k]=0;
      if(dis[(k+b)%a]>dis[k]+b)
    {
      dis[(k+b)%a]=dis[k]+b;
      if(!vis[(k+b)%a])q[++tl]=(k+b)%a,vis[(k+b)%a]=1;
    }
      if(dis[(k+c)%a]>dis[k]+c)
    {
      dis[(k+c)%a]=dis[k]+c;
      if(!vis[(k+c)%a])q[++tl]=(k+c)%a,vis[(k+c)%a]=1;
    }
    }
  for(int i=0;i<a;i++)if(dis[i]<=h)ans+=(h-dis[i])/a+1;
  printf("%lld",ans);
  return 0;
}

原文地址:https://www.cnblogs.com/Narh/p/9275440.html

时间: 2024-10-05 01:00:20

poj 3539 Elevator——同余类bfs的相关文章

[POJ] 3539 Elevator

http://poj.org/problem?id=3539 给定一个电梯,可以上升a,b,c层和回到1层,给定楼高h,求可达层数 lyd讲的同余类BFS,方法是先把三个量压成两个,即把h%a,因为对于一个x∈{h%a},若x可达,则x+ak一定可达. 然后考虑在这个模a的剩余系中,b和c的情况. 从1开始连边,从点i连向(i+w)%a,代价为w,其中w为b或c. 意义就是,对于一个楼层x,从x到达最近x+w层的代价为w,这很显然. 从1开始做单源最短路,然后只需要统计dis小于等于h的,大于的

「POJ3539」Elevator - 同余类最短路

->戳我进原题 Elevator Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 1572 Accepted: 424 Case Time Limit: 2000MS Description Edward works as an engineer for Non-trivial Elevators: Engineering, Research and Construction (NEERC). His new task is

POJ 3278 Catch That Cow --- 简单BFS

/* POJ 3278 Catch That Cow --- 简单BFS */ #include <cstdio> #include <queue> #include <cstring> using namespace std; const int maxn = 100005; bool visit[maxn]; int step[maxn]; int bfs(int n, int k){ if (n == k) return 0; memset(visit, 0, s

hdu 1664 Different Digits, spoj 3929 , 同余,bfs

Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 820    Accepted Submission(s): 202 Problem Description Given a positive integer n, your task is to find a positive integer m, which is a multiple

POJ 2243 || HDU 1372:Knight Moves(BFS)

Knight Moves Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11223 Accepted: 6331 Description A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visit

POJ 3278 Catch That Cow(BFS 剪枝)

题目链接:http://poj.org/problem?id=3278 这几次都是每天的第一道题都挺顺利,然后第二道题一卡一天. = =,今天的这道题7点40就出来了,不知道第二道题在下午7点能不能出来.0 0 先说说这道题目,大意是有个农夫要抓牛,已知牛的坐标,和农夫位置.而且农夫有三种移动方式,X + 1,X - 1,X * 2,问最少几步抓到牛. 开始认为很简单的,三方向的BFS就能顺利解决,然后在忘开标记的情况下直接广搜,果然TLE,在你计算出最少位置之前,牛早跑了. 然后反应过来开标记

Poj 3087 Shuffle&#39;m Up 【BFS】

Shuffle'm Up Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6556 Accepted: 3077 Description A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks of pok

poj 3126 Prime Path 【暴力BFS】

题意:给你一个4位数,再给你一个4位数,如前一个数的每次只移动一位,问你能不能将第一个数变成第二个. 转移条件:1,只能通过素数作为中转,2,每次移动一位. 如果找到输出最少的转移次数(或步数), 如果找不到输出Impossible. 策略:如题. 直接上代码: #include<stdio.h> #include<string.h> #include<queue> #define M 10005 using std::queue; int vis[10000]; in

POJ 1130(一道纯水,bfs+dfs)

POJ 1130 大概题意:给出一副图,求从起点到终点 (0->ET) 必须经过的一点. 我的思路:首先DFS求出经过每点的次数,必过的一点的次数一定最高,但是就这样吗?有可能有多个必过的点,所以还要找出离ET最近的点,这里就利用BFS逐层搜索的性质求每点到ET的距离. #include<iostream> #include<cstdio> #include<string.h> #include<iomanip> #include<queue&g