• [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的,大于的显然不可达了。

    因为是在模a剩余系下做的,所以对于一个满足dis[u]<=h的u,它是一个剩余系的代表元,要算出剩余系大小。

    //drunk,fix later
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    
    typedef long long ll;
    
    const int MAXN=100005;
    
    struct Edge{
      int next,to;
      ll w;
    }e[MAXN<<2];
    int ecnt,head[MAXN];
    inline void add(int x,int y,ll w){
      e[++ecnt].next = head[x];
      e[ecnt].to = y;
      e[ecnt].w = w;
      head[x] = ecnt;
    }
    
    ll h,a,b,c;
    
    queue<int> Q;
    int inq[MAXN];
    ll dis[MAXN];
    void spfa(){
      for(int i=0;i<=a;i++) dis[i]=1ll<<60;
      Q.push(1);inq[1]=1;dis[1]=1;
      while(!Q.empty()){
        int top=Q.front();Q.pop();inq[top]=0;
        for(int i=head[top];i;i=e[i].next){
          int v=e[i].to;
          if(dis[v]>dis[top]+e[i].w){
            dis[v]=dis[top]+e[i].w;
            if(!inq[v]) Q.push(v),inq[v]=1;
          }
        }
      }
    }
    
    int main(){
      cin>>h>>a>>b>>c;
      if(a>b) swap(a,b);
      if(a>c) swap(a,c);
      if(a==1) return cout<<h,0;
      for(int i=0;i<a;i++){
        add(i,(i+b)%a,b);
        add(i,(i+c)%a,c);
      }
      ll sum=0;
      spfa();
      for(int i=0;i<a;i++) if(dis[i]<=h) sum+=(ll)(h-dis[i])/a+1;
      cout<<sum;
      return 0;
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9281134.html

  • 相关阅读:
    线程安全(1)--demo1
    java--构造器与static
    I/O---读取txt文件----demo
    阳光餐厅--oracle---建表---danrong
    定位程序问题出现的原因工具-jstack
    守护线程
    线程的交互:互斥与同步
    正确的停止java中的线程
    使用GSON来生成JSON数据
    使用JSONObject类来生成json格式的数据
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9281134.html
Copyright © 2020-2023  润新知