zoukankan      html  css  js  c++  java
  • poj3539 Elevator——同余类bfs

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

    题目大意是给定 a, b, c,求 1~h 内有多少个数可以被 a, b, c 通过加减法组成;

    这是今天刚讲的神奇的——同余类 bfs 问题!

    大概就是选定一个模数,就选最小的(常数可能会比较小?),不妨令作 a,构建一系列点,组成 mod a 剩余系;

    然后我们要找到每个点的最小可达数,然后它加上若干个 a 就都是可达的;

    对于一个点 x,它可以转移到 (x + b) % b,代价是 b ;c 同理;

    从起点开始 bfs,对于本题来说就是1%a,且 dis[1%a] = 1(层数),求出 dis[] 数组,就是每个点的最小可达数;

    计算答案就是对于每个余数(点),看看在1~h 中有多少个它加若干 a 可达的数,也就是 (h - dis[x]) / a + 1;

    不过其实不 bfs 也可以,反正就是求最短路;

    注意 dis 是 long long 哟~

    代码如下:

    dijkstra:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    int const maxn=1e5+5;
    ll h,ans,dis[maxn];
    int a,b,c,hd[maxn],ct;
    priority_queue<pair<ll,int> >q;
    bool vis[maxn];
    struct N{
        int to,nxt,w;
        N(int t=0,int n=0,int w=0):to(t),nxt(n),w(w) {}
    }ed[maxn<<1];
    void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
    void dijkstra()
    {
        memset(dis,0x3f,sizeof dis);
        dis[1%a]=1; q.push(make_pair(-1,1%a));
        while(q.size())
        {
            int x=q.top().second; q.pop();
            if(vis[x])continue;
            vis[x]=1;
            for(int i=hd[x];i;i=ed[i].nxt)
            {
                int u=ed[i].to;
                if(dis[u]>dis[x]+ed[i].w)
                {
                    dis[u]=dis[x]+ed[i].w;
                    q.push(make_pair(-dis[u],u));
                }
            }
        }
    }
    int main()
    {
        scanf("%lld%d%d%d",&h,&a,&b,&c);
        if(a>b)swap(a,b); if(a>c)swap(a,c);
        for(int i=0;i<a;i++)
        {
            add(i,(i+b)%a,b);
            add(i,(i+c)%a,c);
        }
        dijkstra();
        for(int i=0;i<a;i++)
        {
            if(dis[i]>h)continue;//!
            ans+=(ll)(h-dis[i])/a+1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    dijkstra

    spfa:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    int const maxn=1e5+5;
    ll h,ans,dis[maxn];
    int a,b,c,hd[maxn],ct;
    queue<int>q;
    bool vis[maxn];
    struct N{
        int to,nxt,w;
        N(int t=0,int n=0,int w=0):to(t),nxt(n),w(w) {}
    }ed[maxn<<2];
    void add(int x,int y,int z){ed[++ct]=N(y,hd[x],z); hd[x]=ct;}
    void spfa()
    {
        memset(dis,0x3f,sizeof dis);
        dis[1%a]=1; q.push(1%a); vis[1%a]=1;
        while(q.size())
        {
            int x=q.front(); q.pop(); vis[x]=0;
            for(int i=hd[x];i;i=ed[i].nxt)
            {
                int u=ed[i].to;
                if(dis[u]>dis[x]+ed[i].w)
                {
                    dis[u]=dis[x]+ed[i].w;
                    if(!vis[u])vis[u]=1,q.push(u);
                }
            }
        }
    }
    int main()
    {
        scanf("%lld%d%d%d",&h,&a,&b,&c);
        if(a>b)swap(a,b); if(a>c)swap(a,c);
        for(int i=0;i<a;i++)
        {
            add(i,(i+b)%a,b);
            add(i,(i+c)%a,c);
        }
        spfa();
        for(int i=0;i<a;i++)
        {
            if(dis[i]>h)continue;//!
            ans+=(ll)(h-dis[i])/a+1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    spfa

    bfs:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long ll;
    int const maxn=1e5+5;
    ll h,ans;
    ll a,b,c,dis[maxn];//ll
    queue<int>q;
    bool vis[maxn];
    void bfs()
    {
        memset(dis,0x3f,sizeof dis);
        dis[1%a]=1; q.push(1%a); vis[1%a]=1;
        while(q.size())
        {
            int x=q.front(),u; q.pop(); vis[x]=0;
            if(dis[u=(x+b)%a]>dis[x]+b)
            {
                dis[u]=dis[x]+b;
                if(!vis[u])/*vis[u]=1,*/q.push(u);
            }
            if(dis[u=(x+c)%a]>dis[x]+c)
            {
                dis[u]=dis[x]+c;
                if(!vis[u])/*vis[u]=1,*/q.push(u);
            }
        }
    }
    int main()
    {
        scanf("%lld%lld%lld%lld",&h,&a,&b,&c);
        if(a>b)swap(a,b); if(a>c)swap(a,c);
        bfs();
        for(int i=0;i<a;i++)
        {
            if(dis[i]>h)continue;//!
            ans+=(h-dis[i])/a+1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    MySQL的注入过程
    nmap 扫描器的功能
    用dvwa演示带有用户令牌(user_token)的暴力破解
    在python中安装requests模块
    如何发现struts2漏洞
    vs2017的主题颜色的配置
    在vs上开发linux c++
    linux主机之间的SSH链接
    verilog 实用的小技巧
    verilog 实现DDS
  • 原文地址:https://www.cnblogs.com/Zinn/p/9275321.html
Copyright © 2011-2022 走看看