1. 程式人生 > >[POJ] 3539 Elevator

[POJ] 3539 Elevator

pan 只需要 大小 class 大於 ret tor next iostream

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; }

[POJ] 3539 Elevator