ZOJ 3719 Diablo III 动态规划

本文介绍了一种使用动态规划算法解决游戏战斗策略问题的方法。针对游戏中敌人类型(小怪和Boss),通过计算英雄击败Boss所需的最少药物数量来最大化获得史诗装备的数量。

原题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5042

题意:

游戏中敌人分为小怪和boss两种,杀一个小怪可以叠一层buff,最高5层,叠满buff时杀死boss可以掉史诗,同时buff归0

现在有N个敌人,必须依次击杀,当然也可以跳过,如果敌人是boss,则有血量h[i], 攻击力d[i]

我放英雄的血量是H,攻击为D,可以无限嗑药,每次加血量为P

与小怪战斗可以秒杀,和boss战斗时,双方初始满血,每回合我方英雄先手攻击,同时每回合可以选择嗑药或者不磕

问最多能获得多少件史诗,在此情况下最少要磕多少药


解题思路:

首先要解决的问题是,已知我放英雄和boss的属性,求最少要嗑多少药才能杀死boss

设dp状态 dp[hero][boss][ack] 表示我方英雄当前血量是hero,boss血量为boss,boss攻击力为ack的情况下,最少还要嗑多少药才能杀死boss

若 D >= boss,则本回合可击杀boss, dp[hero][boss][ack] = 0;

然后考虑嗑药的时间,可以选择在被boss攻击前嗑药,也可以在被boss攻击后嗑药或不嗑药,当然前提是挨揍之后不会死....

不嗑药时 dp[hero][boss][ack] = dp[hero-ack][boss-D][ack]

先嗑药时 dp[hero][boss][ack] = dp[min(hero + P, H)-ack][boss-D][ack] + 1

后嗑药时 dp[hero][boss][ack] = dp[min(hero - ack + P, H)][boss-D][ack] + 1

这里需要注意的是嗑药之后不能把HP上限给爆了,同时不要陷入嗑药一定先嗑的误区...

另外,如果先嗑药都抗不住boss的攻击的话,就挂了...


如果解决了上述问题,接下来的问题就不难了,要根据已有的敌人信息求最多能得多少史诗装备

比较容易想到的是dp[i][j][k]表示在前i个敌人得到j个装备且当前buff为k层,最少要磕多少药

但是N有5W,状态开不下,所以我们倒过来考虑,令p[i][j] 表示在击杀敌 i 之前,buff已经有了j层,则到最后最多可以获得多少史诗装备

同时k[i][j]表示对应状态要嗑多少药, 状态数是 5W * 6 因为buff最多就5层嘛

然后对于每个状态,显然有 p[i][j] = p[i + 1][j + k] 当i是boss的时候,k == 0,否则k == 1,同时 j + k <= 5

最后对于每个boss,可以再更新 p[i][5] 和 k[i][5]

最终的答案就是 p[1][0] 和 k[1][0],细节可以参考代码


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <ctime>
using namespace std;

#define LL long long
#define ULL unsigned long long
#define mod 1000000007
#define eps 1e-8
#define MP make_pair

int dp[1001][1001][11], H, D, P;

int F( int hero, int boss, int ack ) {
    if( dp[hero][boss][ack] != -1 ) return dp[hero][boss][ack];
    int &ret = dp[hero][boss][ack];
    if( D >= boss ) return ret = 0;
    if( min(hero + P, H) <= ack ) return ret = 0x3f3f3f3f;
    ret = 0x3f3f3f3f;
    if( hero > ack ) {
        ret = min(ret, F(hero - ack, boss - D, ack));
        ret = min(ret, F(min(hero - ack + P, H), boss - D, ack) + 1);
    }
    ret = min(ret, F(min(hero + P, H) - ack, boss - D, ack) + 1);
    return ret;
}

int b[50005], h[50005], d[50005], n;
int p[50005][6], k[50005][6];

void solve() {
    memset(dp, -1, sizeof(dp));
    memset(p, 0, sizeof(p));
    memset(k, 0, sizeof(k));
    for( int i = n; i >= 1; --i ) {
        for( int j = 0; j < 5; ++j ) {
            p[i][j] = p[i+1][j+1-b[i]];
            k[i][j] = k[i+1][j+1-b[i]];
        }
        p[i][5] = p[i+1][5], k[i][5] = k[i+1][5];
        if( b[i] ) {
            int cost = F(H, h[i], d[i]);
            if( cost != 0x3f3f3f3f ) {
                if( p[i][5] > p[i+1][0] + 1 ) continue;
                if( p[i][5] == p[i+1][0] + 1 && k[i][5] <= k[i+1][0] + cost ) continue;
                p[i][5] = p[i+1][0] + 1;
                k[i][5] = k[i+1][0] + cost;
            }
        }
    }
    printf( "%d %d\n", p[1][0], k[1][0] );
}

int main()
{
    //ios_base::sync_with_stdio(false);
    while( scanf( "%d", &n ) != EOF ) {
        for( int i = 1; i <= n; ++i ) {
            scanf( "%d", b + i );
            if( b[i] ) scanf( "%d%d", h + i, d + i );
        }
        scanf( "%d%d%d", &H, &D, &P );
        solve();
    }
    return 0;
}


本指南详细阐述基于Python编程语言结合OpenCV计算机视觉库构建实时眼部状态分析系统的技术流程。该系统能够准确识别眼部区域,并对眨眼动作与持续闭眼状态进行判别。OpenCV作为功能强大的图像处理工具库,配合Python简洁的语法特性与丰富的第三方模块支持,为开发此类视觉应用提供了理想环境。 在环境配置阶段,除基础Python运行环境外,还需安装OpenCV核心模块与dlib机器学习库。dlib库内置的HOG(方向梯度直方图)特征检测算法在面部特征定位方面表现卓越。 技术实现包含以下关键环节: - 面部区域检测:采用预训练的Haar级联分类器或HOG特征检测器完成初始人脸定位,为后续眼部分析建立基础坐标系 - 眼部精确定位:基于已识别的人脸区域,运用dlib提供的面部特征点预测模型准确标定双眼位置坐标 - 眼睑轮廓分析:通过OpenCV的轮廓提取算法精确勾勒眼睑边缘形态,为状态判别提供几何特征依据 - 眨眼动作识别:通过连续帧序列分析眼睑开合度变化,建立动态阈值模型判断瞬时闭合动作 - 持续闭眼检测:设定更严格的状态持续时间与闭合程度双重标准,准确识别长时间闭眼行为 - 实时处理架构:构建视频流处理管线,通过帧捕获、特征分析、状态判断的循环流程实现实时监控 完整的技术文档应包含模块化代码实现、依赖库安装指引、参数调优指南及常见问题解决方案。示例代码需具备完整的错误处理机制与性能优化建议,涵盖图像预处理、光照补偿等实际应用中的关键技术点。 掌握该技术体系不仅有助于深入理解计算机视觉原理,更为疲劳驾驶预警、医疗监护等实际应用场景提供了可靠的技术基础。后续优化方向可包括多模态特征融合、深度学习模型集成等进阶研究领域。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值