BZOJ 3875: [Ahoi2014]骑士游戏
2016-03-05 20:48
260 查看
BZOJ 3875: [Ahoi2014]骑士游戏
标签(空格分隔): OI-BZOJ OI-DP OI-SFPA OI-DijkstraTime Limit: 30 Sec
Memory Limit: 256 MB
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<=210^5,1<=Ri,Sigma(Ri)<=10^6,1<=Ki,Si<=510^14
Solution
这是一道dp题。\(f_i\)表示杀死i的代价
\(f_i=min(K_i,S_i+\sum\limits_{j=1}^{R_i}f_j)\)
发现会有环的情况。\(f_i\)非负,可以使用Dijkstra算法,或者SPFA对\(f_i\)进行更新
Code
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<set> #include<map> #include<bitset> #include<vector> using namespace std; #define PA pair<int,int> long long read() { long long s=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();} return s*f; } //smile please int N; double f[200005],g[200005]; int be[200005],bn[1000005],bv[1000005],bw=1; void put(int u,int v) {bw++;bn[bw]=be[u];be[u]=bw;bv[bw]=v;} PA MP(int a,int b){PA c;c.first=a*-1,c.second=b;return c;} priority_queue<PA>q; int main() { N=read(); for(int i=1;i<=N;i++) {g[i]=read(),f[i]=read(); int r=read(); for(int j=1;j<=r;j++) put(read(),i); } for(int i=1;i<=N;i++) for(int j=be[i];j;j=bn[j]) g[bv[j]]+=f[i]; for(int i=1;i<=N;i++) q.push(MP(min(g[i],f[i]),i)); while(!q.empty()) {double S=q.top().first*-1;int x=q.top().second;q.pop(); if(S>min(g[x],f[x]))continue; if(g[x]<f[x]) {double del=f[x]-g[x];f[x]=g[x]; for(int i=be[x],v;i;i=bn[i]) {v=bv[i]; g[v]-=del; if(g[v]<f[v]) q.push(MP(min(g[v],f[v]),v)); } } } cout<<((long long)f[1])<<endl; return 0; }
相关文章推荐
- Java堆内存
- win7下Trim启用的验证方法
- 微信红包接口API实现(php版)
- “老子化胡”和白马寺焚经
- 本次孩子流感总结
- Android实现后台长期监听时间变化
- 《信息资源管理》之前五章细化总结
- Spring连接mysql数据库错误:Cannot load JDBC driver class '${driver}'
- AS导入外部项目
- 找工作——JVM内存管理
- ZOJ-1045
- JAVA常用基础知识点[继承,抽象,接口,静态,枚举,反射,泛型,多线程...]
- jQuery——语法
- location.replace与location.href,location.reload的区别
- 1104. Sum of Number Segments (20)
- lamp的403问题
- .使用malloc开辟一个3*4的二维数组,并将内容初始化为0-11
- 谈谈iOS开发中的frame、bounds和center
- Activity的三种启动方式
- 使用modelDriven的好处及原理