zoukankan      html  css  js  c++  java
  • 【JZOJ3674】【luoguP4042】【BZOJ3875】骑士游戏

    description

    在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。当然了,一般来说,相比普通攻击,法术攻击会消耗更多的体力值(但由于游戏系统bug,并不保证这一点)。

    游戏世界中一共有N种不同的怪兽,分别由1到N编号,现在1号怪兽入侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢?


    analysis

    • 可以设(f[i])表示彻底杀死(i)怪兽的最小值,则(f[i]=min(k[i],s[i]+sum_{jin son}f[j]))

    • 但是这种转移可以成环,所以不能用(DP)做,而这种类似松弛操作可以用(SPFA)来做

    • 由于初始不知道从哪个点开始更新会最优,初始所有点都入队

    • (dis[i])表示最小花费,一开始也不知道物理攻击以后如何转化,先都赋值成(k[i])

    • 更新(now)即为枚举所有(now)的儿子,拿(sum_{jin son}dis[j])来更新(dis[now])

    • 对于队首(now)的更新,它的变动可能影响到所有经平A后可以得到(now)的点

    • 所以建反向边,若队首更新成功,把可以得到队首的点全部再入队

    • (dis[1])即为答案。这个做法时间复杂度应该是很大的……


    code

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    #define MAXN 200005
    #define MAXM 1000005
    #define ll long long
    #define reg register ll
    #define fo(i,a,b) for (reg i=a;i<=b;++i)
    #define fd(i,a,b) for (reg i=a;i>=b;--i)
    #define rep(i,a) for (reg i=las[a];i;i=nex[i])
    #define rep1(i,a) for (reg i=las1[a];i;i=nex1[i])
    
    using namespace std;
    
    ll las[MAXM],nex[MAXM],tov[MAXM];
    ll las1[MAXM],nex1[MAXM],tov1[MAXM];
    ll dis[MAXN],phy[MAXN];
    ll n,tot,tot1;
    bool bz[MAXN];
    queue<ll>q;
    
    inline ll read()
    {
    	ll x=0,f=1;char ch=getchar();
    	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
    	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
    	return x*f;
    }
    inline ll max(ll x,ll y){return x>y?x:y;}
    inline ll min(ll x,ll y){return x<y?x:y;}
    inline void link(ll x,ll y){nex[++tot]=las[x],las[x]=tot,tov[tot]=y;}
    inline void link1(ll x,ll y){nex1[++tot1]=las1[x],las1[x]=tot1,tov1[tot1]=y;}
    int main()
    {
    	freopen("knight.in","r",stdin);
    	freopen("knight.out","w",stdout);
    	n=read();
    	fo(i,1,n)
    	{
    		phy[i]=read(),dis[i]=read();ll tmp=read(),x;
    		while (tmp--)x=read(),link(i,x),link1(x,i);
    	}
    	fo(i,1,n)q.push(i);
    	while (!q.empty())
    	{
    		ll now=q.front(),tmp=0;
    		q.pop(),bz[now]=1;
    		rep(i,now)tmp+=dis[tov[i]];
    		if (phy[now]+tmp<dis[now])
    		{
    			dis[now]=phy[now]+tmp;
    			rep1(i,now)if (bz[tov1[i]])q.push(tov1[i]),bz[tov1[i]]=0;
    		}
    	}
    	printf("%lld
    ",dis[1]);
    	return 0;
    }
    
  • 相关阅读:
    卡拉OK歌词原理和实现高仿Android网易云音乐
    LRC歌词原理和实现高仿Android网易云音乐
    Android项目实战之高仿网易云音乐创建项目和配置
    Android项目实战之高仿网易云音乐项目介绍
    WPS for Linux 与统一操作系统 UOS 完成适配,WP越来越强大
    2020 年,Linux 设备或将爆炸式增长
    随机电话号码生成器怎么在线使用?
    Chrome是老大,Firefox 是老二,Edge 不是老三
    2020 年的云世界三个方面:新联盟、无服务器和安全挑战
    电话号码生成器手机版,苹果和安卓手机均可用
  • 原文地址:https://www.cnblogs.com/horizonwd/p/12039714.html
Copyright © 2011-2022 走看看