1. 程式人生 > >poj 3539 Elevator——同余類bfs

poj 3539 Elevator——同余類bfs

oid 需要 const long long sed print spa href i++

題目: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;
}

poj 3539 Elevator——同余類bfs