骑士游戏

题目大意

我们定义dis[i]代表完全杀死i号怪兽的最小体力值花费,那么初始值都是法术攻击的花费。

那么动态转移方程就是:dis[i]=min(magic[i],common[i]+∑son:(dis[i]))

但是我们会发现直接搞dp的话是有后效性的,比如:1-->2-->1那么就会陷入死循环

但是我们惊奇的发现这个好像和SPFA的松弛操作有一些相像,所以我们改变思路,跑一遍SPFA

由于从起点开始跑等于直接比较儿子节点的魔法费用,显然是错误的,所以将所有点全部压入队列中进行考虑

并且如果一个节点的儿子节点被考虑过之后,父节点也会受影响,所以也要重新决策一次

时间复杂度可以看作是SPFA的复杂度上加一个小常数,具体不会证,注意常数优化

最后,附上本题代码:(自动省略头文件)

 1 il LL read()
 2 {
 3     reg LL w=0;
 4     char ch=getchar();
 5     while(ch<‘0‘||ch>‘9‘) ch=getchar();
 6     while(ch>=‘0‘&&ch<=‘9‘)
 7     {
 8         w=(w<<3)+(w<<1)+ch-‘0‘;
 9         ch=getchar();
10     }
11     return w;
12 }
13 struct EDGE
14 {
15     int to,nxt;
16 };
17 EDGE edge[maxm+5],rev[maxm + 5];
18 int n,cnt;
19 LL dis[maxn+5],c[maxn+5];
20 int head[maxn+5];
21 bool vis[maxn+5];
22 queue<int>q;
23
24 il void add(int x,int y)
25 {
26     edge[++cnt].to=y;
27     edge[cnt].nxt=head[x];
28     head[x]=cnt;
29 }
30 int fir[maxn + 5],alloc;
31 il void addrev(int u,int v)
32 {
33     rev[++alloc].nxt = fir[u];
34     fir[u] = alloc;
35     rev[alloc].to = v;
36 }
37 il void SPFA()
38 {
39     UF(i,1,n) q.push(i),vis[i]=1;
40     while(!q.empty())
41     {
42         reg int s=q.front();
43         reg LL res=c[s];
44         vis[s]=0,q.pop();
45         for(reg int i=head[s]; i; i=edge[i].nxt) res+=dis[edge[i].to];
46         if(res<dis[s])
47         {
48             dis[s]=res;
49             for(reg int i=fir[s];i;i=rev[i].nxt) if(vis[rev[i].to]==0) q.push(rev[i].to),vis[rev[i].to]=1;
50         }
51     }
52 }
53 int main()
54 {
55     scanf("%d",&n);
56     UF(i,1,n)
57     {
58         c[i] = read(),dis[i] = read();
59         int z;
60         scanf("%d",&z);
61         UF(j,1,z)
62         {
63             int k;
64             scanf("%d",&k);
65             add(i,k);
66             addrev(k,i);
67         }
68     }
69     SPFA();
70     printf("%lld\n",dis[1]);
71     return 0;
72 }

原文地址:https://www.cnblogs.com/yufenglin/p/10885407.html

时间: 2024-10-12 02:36:13

骑士游戏的相关文章

BZOJ 3875 Ahoi2014 骑士游戏

3875: [Ahoi2014]骑士游戏 Time Limit: 30 Sec  Memory Limit: 256 MB Description [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击.两种攻击方式都会消耗JYY一些体力.采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个

「AHOI2014/JSOI2014」骑士游戏

「AHOI2014/JSOI2014」骑士游戏 传送门 考虑 \(\text{DP}\). 设 \(dp_i\) 表示灭种(雾)一只编号为 \(i\) 的怪物的代价. 那么转移显然是: \[dp_i = \min(K_i, S_i + \sum_{j = 1}^{R_i} dp_{v_j})\] 但是我们会发现这个东西是有后效性的... 所以我们会想要用建图然后跑一个最短路什么的来搞... 于是我们观察到上面那个 \(\text{DP}\) 式子中,\(dp_i\) 如果用后面那一项来转移,显然

bzoj3875 [Ahoi2014]骑士游戏

Description [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击.两种攻击方式都会消耗JYY一些体力.采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽:而采用法术攻击则可以彻底将一个怪兽杀死.当然了,一般来说,相比普通攻击,

BZOJ3875: [Ahoi2014&amp;Jsoi2014]骑士游戏

Description [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻 击.两种攻击方式都会消耗JYY一些体力.采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能经过若干次普通攻击后变回一个或更多同样的怪兽:而采用法术攻击则可以彻底将一个怪兽杀死.当然了,一般来说,相比普通攻

[BZOJ3875][AHOI2014]骑士游戏(松弛操作)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3875 分析: 类似于spfa求最短路,设d[i]表示完全消灭i号怪物的最小花费,我们对d[]进行动态更新 我们可以把问题反向:一开始所有怪物都存活,我们要找到一个怪物合成方案合成1号怪物,其中合成方法有两种,一种是魔法攻击逆向产生怪物,另一种就是由某个怪物的后继怪物合成此怪物 对于第一种产生方法的表示,令初始的d[i]=k[i]即可 对于第二种产生方法的表示,也就是算法的核心——类似

【BZOJ3875】【Ahoi2014】骑士游戏 SPFA处理有后效性动规

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44040735"); } 题解: 首先一个点可以分裂成多个新点,这样就有了图上动规的基础. 即f[i]表示i点被消灭的最小代价,它可以由分裂出的点们更新. 但是这个东西有后效性,所以我们用SPFA来处理它. spfa处理后效性动规 我

BZOJ 3875 Ahoi2014 骑士游戏 SPFA

题目大意:给定n个怪物,每个怪物可以用魔法直接干掉,或者用物理攻击使其分裂为一些其他怪物,求杀掉1号怪物的最小花销 令f[i]为杀死i号怪物的最小花销,则f[i]=min(k[i],s[i]+Σf[j]) 其中j为i用物理攻击后可以分裂为的怪物 但是直接DP有后效性,因此我们用SPFA来跑这个DP即可 注意如果每次更新一个点之后都重新计算花销会T掉 改成减掉花销的差值就好了 具体写法去看代码吧- - #include <cstdio> #include <cstring> #inc

【BZOJ3875】[Ahoi2014]骑士游戏【最短路】【DP】

[题目链接] 对于怪物u,普通攻击打死后产生的怪物为vi.设dis[u]表示打死u的最小花费,那么有 dis[u] = min{s[u] + ∑dis[vi], k[u]} 以这个为松弛条件,跑spfa就可以啦. 然而BZOJ跑了29s...变为倒数rank1 /* Telekinetic Forest Guard */ #include <cstdio> #include <cstring> #include <algorithm> using namespace s

[AHOI2014/JSOI2014]骑士游戏

题目 思博贪心题写了一个半小时没救了,我也没看出这是一个\(spfa\)来啊 设\(dp_i\)表示彻底干掉第\(i\)只怪物的最小花费,一个非常显然的事情,就是对于\(k_i\)值最小的怪物满足\(dp_i=k_i\) 非常好理解,反正到最后都要干掉这个怪物,何必再把它干成别的怪物 于是我们按照\(k_i\)的值先排序一下,另外维护一个小根堆 如果堆里没有点或者堆顶的\(dp\)值比当前的\(k\)要大,我们直接令当前当前\(k_i\)值最小的点\(i\)的\(dp_i=k_i\),之后遍历所