码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ3875 [Ahoi2014]骑士游戏

时间:2016-08-11 15:31:37      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

Description

 【故事背景】
长期的宅男生活中,JYY又挖掘出了一款RPG游戏。在这个游戏中JYY会
扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽。
【问题描述】
在这个游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻
击。两种攻击方式都会消耗JYY一些体力。采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个怪兽可能 经过若干次普通攻击后变回一个或更多同样的怪兽;而采用法术攻击则可以彻底将一个怪兽杀死。当然了,一般来说,相比普通攻击,法术攻击会消耗更多的体力值 (但由于游戏系统bug,并不保证这一点)。
游戏世界中一共有N种不同的怪兽,分别由1到N编号,现在1号怪兽入
侵村庄了,JYY想知道,最少花费多少体力值才能将所有村庄中的怪兽全部杀死呢?

Input

第一行包含一个整数N。
接下来N行,每行描述一个怪兽的信息;
其中第i行包含若干个整数,前三个整数为Si,Ki和Ri,表示对于i号怪兽,
普通攻击需要消耗Si的体力,法术攻击需要消耗Ki的体力,同时i号怪兽死亡后会产生Ri个新的怪兽。表示一个新出现的怪兽编号。同一编号的怪兽可以出现多个。
 

Output

 输出一行一个整数,表示最少需要的体力值。

Sample Input

4
4 27 3 2 3 2
3 5 1 2
1 13 2 4 2
5 6 1 2

Sample Output

26

HINT

【样例说明】

首先用消耗4点体力用普通攻击,然后出现的怪兽编号是2,2和3。花费

10点体力用法术攻击杀死两个编号为2的怪兽。剩下3号怪兽花费1点体力进

行普通攻击。此时村庄里的怪兽编号是2和4。最后花费11点体力用法术攻击

将这两只怪兽彻底杀死。一共花费的体力是4+5+5+1+5+6=26。

【数据范围】

2<=N<=2*10^5,1<=Ri,Sigma(Ri)<=10^6,1<=Ki,Si<=5*10^14

 

 

正解:SPFA+有后效性DP

解题报告:

  考虑直接DP,显然有后效性,会不断影响到之前的所有结点。那么我们用SPFA维护更新操作,保证每次更新能够使所有可更新的结点被更新。

  最开始把所有结点加入队列,因为最开始都可以被更新。

  记得开long long  

 

 

 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32   
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 200011;
21 const int MAXM = 4000011;
22 int n,m;
23 LL f[MAXN],g[MAXN];//f[i]表示消灭掉i的最小花费,g[i]表示物理攻击i后并消灭产生新怪物后的开销
24 int first[MAXN],next[MAXM],to[MAXM];
25 int head[MAXN],ecnt,ccnt;
26 bool vis[MAXN];
27 queue<int>Q;
28 struct edge{
29     int next,to;
30 }e[MAXM];
31 
32 inline int getint()
33 {
34        int w=0,q=0;
35        char c=getchar();
36        while((c<0 || c>9) && c!=-) c=getchar();
37        if (c==-)  q=1, c=getchar();
38        while (c>=0 && c<=9) w=w*10+c-0, c=getchar();
39        return q ? -w : w;
40 }
41 
42 inline LL getlong()
43 {
44        LL w=0,q=0;
45        char c=getchar();
46        while((c<0 || c>9) && c!=-) c=getchar();
47        if (c==-)  q=1, c=getchar();
48        while (c>=0 && c<=9) w=w*10+c-0, c=getchar();
49        return q ? -w : w;
50 }
51 
52 inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
53 
54 inline void link2(int x,int y){  e[++ccnt].next=head[x]; head[x]=ccnt; e[ccnt].to=y; }
55 
56 inline void SPFA(){
57     while(!Q.empty()) {
58     int u=Q.front(); Q.pop(); vis[u]=0;
59     if(f[u]<=g[u]) continue;//已经更优
60     for(int i=head[u];i;i=e[i].next) {
61         if(!vis[e[i].to]) vis[e[i].to]=1,Q.push(e[i].to);
62         g[e[i].to]-=f[u];
63         g[e[i].to]+=g[u];
64     }
65     f[u]=g[u];//存在更优的策略
66     }
67 }
68 
69 inline void work(){
70     n=getint(); int x;
71     for(int i=1;i<=n;i++) { 
72     g[i]=getlong();    f[i]=getlong();//初值定为物理攻击和法力攻击
73     m=getint(); Q.push(i); vis[i]=1;
74     for(int j=1;j<=m;j++) x=getint(),link(i,x),link2(x,i);
75     }
76     for(int i=1;i<=n;i++) for(int j=first[i];j;j=next[j]) g[i]+=f[to[j]];
77     SPFA();
78     printf("%lld",f[1]);
79 }
80 
81 int main()
82 {
83   work();
84   return 0;
85 }

 

BZOJ3875 [Ahoi2014]骑士游戏

标签:

原文地址:http://www.cnblogs.com/ljh2000-jump/p/5760926.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!