问题是求一个方案,实际隐含一个dp。法力是递减的,所以状态是DAG,对于一个确定的状态,我们贪心地希望英雄的血量尽量大。

分析:定义状态dp[i][p][h]表示是已经用了i的法力值,怪兽的位置在p,怪兽的总血量为h时候英雄所具有的最大血量,

采用刷表法,决策有:

使用雷击,h变成h-L[p],p变成max(p-V,1),如果怪兽移动结束以后在1号位置且没有击杀怪物h-L[p]>0(注意这种情况),

会对英雄造成ceil((h-L[p])/HPm)点伤害,如果dp[i][p][h]-damge<=0,那么转移是非法的。

使用传送,传送到1是没有意义的,从2开始枚举,假设传送的位置为tp,那么怪物的下一个位置会是max(tp-V,1),处理一下伤害和转移即可。

使用治疗,注意判断一下血量上限。

具体处理的时候,记录一个pre状态数组和相应操作,用一个vis数组表示下一个阶段的状态是否出现过。

习惯用滚动数组,直接写反而觉得别扭。。。

转移麻烦的写个updata效果拔群

#include<bits/stdc++.h>
using namespace std;
const int maxn = ;
int N,HPh,MPh,HPm,Nm,V,dH;
int L[maxn]; #define MP make_pair
typedef pair<int,int> Node;
#define fi first
#define se second
#define PB push_back const int maxh = ;
int dp[][maxn][maxh];
bool vis[maxn][maxh];
char opt[][maxn][maxh];
Node pre[][maxn][maxh];
int optp[][maxn][maxh]; void print_ans(int i,Node rt)
{
printf("VICTORIOUS\n");
stack<Node> S; S.push(rt);
while(i>){
Node &u = S.top();
S.push(pre[i][u.first][u.second]); i--;
}
while(S.size()){
Node &u = S.top();
char ch = opt[i][u.fi][u.se];
putchar(ch);
if(ch == 'T') printf(" %d",optp[i][u.first][u.second]);
putchar('\n');
S.pop();
i++;
}
} void updata(int i,int nps,int Hm,char op,int opp,Node &u,int val,int (*nex)[maxh])
{
opt[i][nps][Hm] = op;//操作指令
optp[i][nps][Hm] = opp;//传送相关
pre[i][nps][Hm] = u;//前驱状态
nex[nps][Hm] = val;//更新val值
} void solve()
{
vector<Node> V1,V2,*q1 = &V1,*q2 = &V2;
q1->PB({N,Nm*HPm}); dp[][N][Nm*HPm] = HPh;
for(int i = ; i < MPh; i++){
memset(vis,,sizeof(vis));
int (*d1)[maxh] = dp[i&], (*d2)[maxh] = dp[(i&)^];//当前状态,和上一层状态
for(int j = ; j < (int)q1->size(); j++){
Node &u = q1->at(j);
//雷击
int nps = max(u.fi-V,);//怪兽移动后的位置 next_pos
int tHp = max(u.se-L[u.fi],);//攻击后怪兽的HP
int val = d1[u.fi][u.se];//英雄血量
int damege = ;
if(nps == ){ damege = (tHp+HPm-)/HPm;}//怪兽移动后到达1号格子,对英雄攻击
if(val-damege> || tHp == ){//英雄能承受攻击 或者 怪物已经死了
if(!vis[nps][tHp]){//状态判重
vis[nps][tHp] = true, q2->PB({nps,tHp});
updata(i,nps,tHp,'L',-,u,val-damege,d2);
if(tHp == ) {
print_ans(i,Node(nps,)); return;
} }else if(d2[nps][tHp] < val-damege){
updata(i,nps,tHp,'L',-,u,val-damege,d2);
if(tHp == ) {
print_ans(i,Node(nps,)); return;
}
}
}
//传送
for(int tp = ; tp <= N; tp++){//传送到tp位置
int tnps = max(tp-V,);//怪物移动 int tval = d1[u.first][u.second];
if(tnps == ){
tval -= (u.se+HPm-)/HPm;
}
if(tval>){
if(!vis[tnps][u.second]){
vis[tnps][u.se] = true,q2->PB({tnps,u.se});
updata(i,tnps,u.se,'T',tp,u,tval,d2);
}else if(d2[tnps][u.second] < tval){
updata(i,tnps,u.se,'T',tp,u,tval,d2);
}
} } if(nps == ){ damege = (u.se+HPm-)/HPm;}//未使用雷击时怪兽造成的伤害
else damege = ;
val = min(d1[u.fi][u.se]+dH,HPh);//治疗
if(val>damege){
val -= damege;
if(!vis[nps][u.se]){
vis[nps][u.se] = true; q2->PB({nps,u.se});
updata(i,nps,u.se,'H',-,u,val,d2);
}else if(d2[nps][u.se] < val){
updata(i,nps,u.se,'H',-,u,val,d2);
}
} }
q1->clear();
swap(q1,q2);
}
puts("DEFEATED");
} int main()
{
freopen("heroes.in","r",stdin);
freopen("heroes.out","w",stdout);
cin>>N>>HPh>>MPh>>HPm>>Nm>>V>>dH;
for(int i = ; i <= N; i++) scanf("%d",L+i);
solve();
return ;
}

2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02) H Heroes Of Might And Magic (隐含dp)的更多相关文章

  1. 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02) A Amusing Numbers (数学)

    其实挺简单的.先直接算出之前已经排在k这个数前面的数字.比如543是三位的,那么100~543都是可以的,两位的10~54. 如果还需要往前面补的话,那么依次考虑1000~5430,5430是上界不能 ...

  2. 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02)

    B Bricks 计算几何乱搞 题意: 给你个立方体,问你能不能放进一个管道里面. 题解: 这是一道非常迷的题,其问题在于,你可以不正着放下去,你需要斜着放.此时你需要枚举你旋转的角度,来判断是否可行 ...

  3. 2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)

    2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) A 题意:有 n 个时刻 ...

  4. Editing 2011-2012 ACM-ICPC Northeastern European Regional Contest (NEERC 11)

    NEERC 11 *wiki链接[[https://acm.ecnu.edu.cn/wiki/index.php?title=2011-2012_ACM-ICPC_Northeastern_Europ ...

  5. 2012-2013 ACM-ICPC Northeastern European Regional Contest (NEERC 12)

    Problems     # Name     A Addictive Bubbles1 addictive.in / addictive.out 2 s, 256 MB    x438 B Blin ...

  6. 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15)C - Cactus Jubilee

    题意:给一颗仙人掌,要求移动一条边,不能放在原处,移动之后还是一颗仙人掌的方案数(仙人掌:无向图,每条边只在一个环中),等价于先删除一条边,然后加一条边 题解:对于一颗仙人掌,分成两种边,1:环边:环 ...

  7. 2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) 日常训练

    A - Archery Tournament 题目大意:按时间顺序出现靶子和射击一个位置,靶子的圆心为(x, y)半径为r,即圆与x轴相切,靶子不会重叠,靶子被击中后消失, 每次射击找出哪个靶子被射中 ...

  8. 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15)

    NEERC 15 题解1 题解2 官方题解

  9. ACM ICPC 2010–2011, Northeastern European Regional Contest St Petersburg – Barnaul – Tashkent – Tbilisi, November 24, 2010

    ACM ICPC 2010–2011, Northeastern European Regional Contest St Petersburg – Barnaul – Tashkent – Tbil ...

随机推荐

  1. 一个基于Tp3.2(thinkphp3.2)的工会管理系统

    该系统包括11个模块. 会员管理模块 奖惩管理模块 运动会管理模块 新闻管理模块 文档管理模块 经费管理模块 电子提案管理模块 用户管理模块 权限管理模块 系统管理模块 系统的登录 系统主页 这里只是 ...

  2. Working Experience - NLog 多实例时配置文件冲突

    正文 问题: 当前项目已使用 NLog 的情况下再引用使用 NLog 的项目, 出现配置文件冲突, 有一个配置文件不工作 方法: 使用 LogFactory 代替 LogManager 来获取 Log ...

  3. 【问题总结】万万没想到,竟然栽在了List手里

    说明 昨天同事开发的时候遇到了一个奇怪的问题. 使用Guava做缓存,往里面存一个List,为了方便描述,称它为列表A,在另一个地方取出来,再跟列表B中的元素进行差集处理,简单来说,就像是下面这样: ...

  4. Golang : cobra 包简介

    Cobra 是一个 Golang 包,它提供了简单的接口来创建命令行程序.同时,Cobra 也是一个应用程序,用来生成应用框架,从而开发以 Cobra 为基础的应用.本文的演示环境为 ubuntu 1 ...

  5. Lightoj1007【欧拉函数-素数表】

    基础题. PS:注意unsigned long long; 以及%llu #include<bits/stdc++.h> using namespace std; typedef unsi ...

  6. Unite Europe案例项目《影子战术》层级优化经验分享

    http://forum.china.unity3d.com/thread-25087-1-9.html 在Unite Europe 2017的Keynote主题演讲中,我们为大家分享了将主机游戏&l ...

  7. Posture Energy——姿态的能量

    人的生活是套路化的,人活得越久,被套路化的概率就越大.普通百姓的生活都如同一个模板刻出来的. 一旦生活微调,我们会突然发现原来几十年的认知有问题,如同重获新生的感觉.譬如:早起,当我们每天早起一小时, ...

  8. Linux上部署黑马旅游网Bug集锦

  9. css3椭圆运动

    通过使用css3实现让元素椭圆运动.而不是圆形运动. 效果1:http://sandbox.runjs.cn/show/ignefell 效果2:http://runjs.cn/code/w2wxjy ...

  10. sonar扫描android项目配置 mac版

    一. 下载安装 JDK8以上  SonarQube   SonarQube Scanner 1. 解压缩SonarQube和SonarQube Scanner,直接运行SonarQube中bin目录下 ...