2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02) H Heroes Of Might And Magic (隐含dp)
问题是求一个方案,实际隐含一个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)的更多相关文章
- 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02) A Amusing Numbers (数学)
其实挺简单的.先直接算出之前已经排在k这个数前面的数字.比如543是三位的,那么100~543都是可以的,两位的10~54. 如果还需要往前面补的话,那么依次考虑1000~5430,5430是上界不能 ...
- 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02)
B Bricks 计算几何乱搞 题意: 给你个立方体,问你能不能放进一个管道里面. 题解: 这是一道非常迷的题,其问题在于,你可以不正着放下去,你需要斜着放.此时你需要枚举你旋转的角度,来判断是否可行 ...
- 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 个时刻 ...
- 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 ...
- 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 ...
- 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15)C - Cactus Jubilee
题意:给一颗仙人掌,要求移动一条边,不能放在原处,移动之后还是一颗仙人掌的方案数(仙人掌:无向图,每条边只在一个环中),等价于先删除一条边,然后加一条边 题解:对于一颗仙人掌,分成两种边,1:环边:环 ...
- 2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) 日常训练
A - Archery Tournament 题目大意:按时间顺序出现靶子和射击一个位置,靶子的圆心为(x, y)半径为r,即圆与x轴相切,靶子不会重叠,靶子被击中后消失, 每次射击找出哪个靶子被射中 ...
- 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15)
NEERC 15 题解1 题解2 官方题解
- 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 ...
随机推荐
- ubuntu 下交叉编译环境的搭建
1. 安装标准的C开发环境,由于Linux安装默认是不安装的,所以需要先安装一下(如果已经安装好的话,就可以免去这一步了): #sudo apt-get install gcc g++ libgcc1 ...
- js关于为DOM对象添加自定义属性的方式和区别
DOM对象的三种在添加自定义属性的方式 一是 通过 “.”+“属性名” 二是 setAttribute()(getAttribute()获取) 三是 直接在元素标签上加属性 如:<div n ...
- John 尼姆博弈
John Little John is playing very funny game with his younger brother. There is one big box filled wi ...
- 在SQL中直接把查询结果转换为JSON数据
下面这篇中,已经有准备一些数据: <MS SQL server对象类型type>https://www.cnblogs.com/insus/p/10903916.html 为前端服务,直接 ...
- 程序员除了会CRUD之外,还应该知道什么叫CQRS!
今天主要跟大家分享一下什么是 CQRS,以及在项目中如何去使用. CRUD系统 我们平常最熟悉的就是三层架构,通常都是通过数据访问层来修改或者查询数据,一般修改和查询使用的是相同的实体.然后通过业 ...
- JAVA之动态编译
通过Java动态生成class文件 今天说下JAVA中的动态编译,这个功能根据我现在的了解好像没有见到过用的,我Jio的吧,现在的一些在线代码编缉器可以用到了,这个具体我也不是很清楚.感兴趣的大家可以 ...
- Linux 中 ip netns 命令
通过 ip netns help 可以查看所有关于ip netns的命令: network namespace 在逻辑上是网络堆栈的一个副本,它有自己的路由.防火墙规则和网络设备. ip netns ...
- 黑马学习Ajax 概念和基本使用
- CC06:像素翻转
题目 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度. 给定一个NxN的矩阵,和矩阵的阶数N,请返 ...
- Java泛型-通配符的上限和下限问题
Java的泛型中,通配符可以设置上限和下限. 上限:<? extends T> ?是T和T的子类 下限:<? super T> ?是T和T的父类 怎么看待这个上限和下限呢 首先 ...