• 【LGOJ3403】跳楼机


    一栋楼共有 h 层,有以下操作:
    1. 向上移动x层
    2. 向上移动y层
    3. 向上移动z层
    4. 回到第一层
    问可以达到的楼层数量
    

    如果令(f(i))表示表示仅通过操作2和操作3能到达的 (mod x=i) 的最小楼层
    那么就有以下方程:

    [f(i+y)=f(i)+y ]

    [f(i+z)=f(i)+z ]

    想一想最短路的转移方程

    [f(v)=f(u)+dis(u,v) ]

    是不是很像?
    所以我们可以建图,把 (i+y)(i+z) 看作点
    (y,z)成为权值,跑spfa算出(f(i))

    由于 (f(i)) 的数量统计时没有使用第一个操作
    所以每增加一个 (x) ,答案都会相应地增加

    注意边界是闭区间,所以答案再+1,即

    [ans+=(h-f(i))/x+1 ]

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    ll h,x,y,z,ans=0;
    ll f[100005];
    struct Edge
    {
    	ll next,to,dis;
    }edge[200005];
    int cnt=0,head[200005];
    
    inline void add_edge(ll from,ll to,ll dis)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	edge[cnt].dis=dis;
    	head[from]=cnt;
    }
    
    template<class T>inline void read(T &res)
    {
    	char c;T flag=1;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    bool vis[100005];
    queue<int> q;
    void spfa()
    {
    	memset(f,0x3f3f3f3f,sizeof(f));
    	memset(vis,0,sizeof(vis));
    	q.push(1);
    	vis[1]=f[1]=1;
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(register int i=head[u];i;i=edge[i].next)
    		{
    			int v=edge[i].to;
    			if(f[v]>f[u]+edge[i].dis)
    			{
    				f[v]=f[u]+edge[i].dis;
    				if(!vis[v])
    				{
    					q.push(v);
    					vis[v]=1;
    				}
    			}
    		}
    	}
    }
    
    int main()
    {
    	read(h);
    	read(x);read(y);read(z);
    	if(x==1||y==1||z==1){printf("%lld
    ",h);return 0;}
    	for(register int i=0;i<x;++i)
    	{
    		add_edge(i,(i+y)%x,y);
    		add_edge(i,(i+z)%x,z);
    	}
    	spfa();
    	for(register int i=0;i<x;++i) if(f[i]<=h) ans+=(h-f[i])/x+1;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    [ZJOJ] 5772【NOIP2008模拟】今天你AK了吗
    exgcd扩展欧几里得求解的个数
    Dinic当前弧优化 模板及教程
    [Luogu] P3907 圈的异或
    提升——树形DP
    C++ 优先队列
    C++ 洛谷 P2458 [SDOI2006]保安站岗 from_树形DP
    C++ 洛谷 2014 选课 from_树形DP
    C++ luogu1352没有上司的舞会 from_树形DP
    浅说——树形DP
  • 原文地址:https://www.cnblogs.com/tqr06/p/11620680.html
Copyright © 2020-2023  润新知