小红的踏前斩——贪心

有 n 个怪物排成一排,第 i 个怪物的血量为 ai。

小红有两个技能可以打怪:
1. 强力攻击,消耗 1 mp,对一只怪物造成1点伤害。
2. 踏前斩,消耗 5 mp,对当前怪物造成 1 点的伤害,同时剑气将波及后两个怪物,对下一个怪物造成 2 点伤害,对下下个怪物造成 3 点伤害。

如果一个怪物受伤后血量小于等于 0,则怪物死亡。死亡后怪物的尸体依然占据一个位置,会被踏前斩的剑气打到。

小红想知道,击杀全部怪物至少需要花费多少mp?

Input
第一行输入一个正整数 n (1 ≤ n ≤ 1e5).
第二行输入 n 个正整数 ai (1 ≤ ai ≤ 1e9).

Output
一个整数,代表花费的mp最小值。

输入1:
5
2 3 4 2 3
输出1:
12

输入2:
6
1 1 2 3 2 3
输出2:
11

样例 1 解释:

对第一个怪和第二个怪分别进行一次强力攻击,此时每只怪物血量为[1,2,4,2,3]
对第一个怪进行一次踏前斩,此时每只怪物血量为[0,0,1,2,3]
再对第三个怪进行一次踏前斩,消灭全部怪物。
总mp消耗为12。

样例 2 解释:

对第二怪进行一次踏前斩后,每只怪物血量为[1,0,0,0,2,3]。
随后对每个怪物进行一次强力攻击。

解析:

从后往前遍历即可,从前向后容易出现前面的影响后面的,从后往前就不会有这种影响。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef pair<int,int> PII;
const double PI=acos(-1.0);
const int N=2e6+10;
int n;
int a[N];
signed main()
{
    ios;
    cin>>n;
    for (int i=1;i<=n;i++) cin>>a[i];
    int ans=0;
    for (int i=n-2;i>0;i--)
    {
        int k=min(a[i],min(a[i+1]/2,a[i+2]/3));
        ans +=5*k;
        a[i] -=k;
        a[i+1] -=2*k;
        a[i+2] -=3*k;
    }
    for (int i=1;i<=n;i++) ans +=a[i];
    cout<<ans;
    return 0;
}

### 饿了么 Java 笔试题及相关解析 以下是关于饿了么 Java 笔试题目的一些典型问题及其解答: #### 1. 字符串重排问题 **输入**: 给定一个字符串 `aabbc` **输出**: 如果无法满足条件则返回 `-1`,否则返回任意合法的字符串。 对于此类问题,可以采用贪心策略来实现。核心思想是尽可能让相邻字符不同[^1]。具体做法如下: - 记录每个字符出现的频率。 - 使用优先队列(大顶堆),每次取出当剩余次数最多的两个字符依次排列。 - 若最终仍有未处理完毕的情况,则说明无解。 ```java import java.util.*; public class StringRearrangement { public static String rearrangeString(String s) { int[] freq = new int[26]; for (char c : s.toCharArray()) { freq[c - 'a']++; } PriorityQueue<Character> pq = new PriorityQueue<>((a, b) -> freq[b - 'a'] - freq[a - 'a']); for (int i = 0; i < 26; i++) { if (freq[i] > 0) { pq.offer((char) ('a' + i)); } } StringBuilder sb = new StringBuilder(); while (!pq.isEmpty()) { char first = pq.poll(); if (sb.length() == 0 || sb.charAt(sb.length() - 1) != first) { sb.append(first); freq[first - 'a']--; if (freq[first - 'a'] > 0) { pq.offer(first); } } else { if (pq.isEmpty()) return "-1"; char second = pq.poll(); sb.append(second); freq[second - 'a']--; if (freq[second - 'a'] > 0) { pq.offer(second); } pq.offer(first); } } return sb.toString(); } public static void main(String[] args) { System.out.println(rearrangeString("aabbc")); // 输出可能为 "cbaba" } } ``` --- #### 2. 动态规划问题——捉迷藏 给定一个小和小紫的游戏场景,计算两人在特定时间内的位置概率分布。 通过动态规划方法解决问题时,定义状态转移方程为 \(dp[t][i][j]\),其中 \(t\) 表示时刻,\(i\) 和 \(j\) 分别代表两人的坐标位置[^2]。初始状态下设置起点的概率为 1,并逐步更新后续的状态。 ```java class HideAndSeek { private final double EPSILON = 1e-9; public double[][][] solve(int n, List<int[]> movesRed, List<int[]> movesBlue) { double[][][] dp = new double[n + 1][n][n]; // 初始化 dp[0][movesRed.get(0)[0]][movesBlue.get(0)[0]] = 1.0; // 转移过程 for (int t = 0; t < n; t++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (Math.abs(dp[t][i][j]) > EPSILON) { // 当有概率存在 for (int k = 0; k < movesRed.size(); k++) { int nextI = movesRed.get(k)[0]; // 下一步移动的位置 dp[t + 1][nextI][j] += dp[t][i][j] / movesRed.size(); } for (int l = 0; l < movesBlue.size(); l++) { int nextJ = movesBlue.get(l)[0]; dp[t + 1][i][nextJ] += dp[t][i][j] / movesBlue.size(); } } } } } return dp; } } ``` --- #### 3. 黑板游戏中的异或运算 针对黑板上的整数集合,求某个数字与现有数字的最大异或值。如果没有可用数据,则返回 \(-1\)[^3]。 解决方案基于字典树结构存储已有数值并快速查询最优匹配项。 ```java import java.util.ArrayList; import java.util.List; class TrieNode { TrieNode children[]; public TrieNode() { this.children = new TrieNode[2]; } } public class MaxXORQuery { private TrieNode root; public MaxXORQuery() { root = new TrieNode(); } public void insert(int num) { TrieNode node = root; for (int i = 31; i >= 0; i--) { int bit = (num >> i) & 1; if (node.children[bit] == null) { node.children[bit] = new TrieNode(); } node = node.children[bit]; } } public int getMaxXorWithNum(int num) { TrieNode node = root; int xorSum = 0; for (int i = 31; i >= 0 && node != null; i--) { int bit = (num >> i) & 1; if (node.children[1 - bit] != null) { xorSum |= (1 << i); node = node.children[1 - bit]; } else { node = node.children[bit]; } } return xorSum; } public static void processQueries(List<Integer> numbers, List<Integer> queries) { MaxXORQuery trie = new MaxXORQuery(); List<Integer> results = new ArrayList<>(); for (Integer query : queries) { if (query.equals(-1)) continue; boolean found = false; int maxVal = Integer.MIN_VALUE; for (Integer number : numbers) { trie.insert(number); int currentMax = trie.getMaxXorWithNum(query); if (currentMax > maxVal) { maxVal = currentMax; found = true; } } if (found) { results.add(maxVal); } else { results.add(-1); } } System.out.println(results); } } ``` --- ####
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值