【题解】 AtCoder beginner Contest 153

ProblemA:Serval vs Monster

题目传送门:https://atcoder.jp/contests/abc153/tasks/abc153_a

解题思路:

问你需要多少次技能才能消灭怪兽。

输出 ⌈ H A ⌉ ⌈\frac{H}{A}⌉ AH即可,可以转化为 ⌊ H + A − 1 A ⌋ \lfloor \frac {H+A-1} A \rfloor AH+A1

代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int h, a;
    cin >> h >> a;
    cout << ceil(h * 1.0 / a) << endl;
    return 0;
}

ProblemB:Common Raccoon vs Monster

题目传送门:https://atcoder.jp/contests/abc153/tasks/abc153_b

解题思路:

给你 H H H N N N N N N个数组成的技能数组 A A A,每个技能只能使用过一遍,问你能不能把怪兽的 H H H减到0以下。

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, t, a;
    cin >> n >> a;
    int tot = 0;
    for(int i = 0; i < a; ++i) {
        cin >> t;
        tot += t;
    }
    if(tot >= n) puts("Yes");
    else puts("No");
 
    return 0;
}

Problem C:Fennec vs Monster

题目传送门:https://atcoder.jp/contests/abc153/tasks/abc153_c

解题思路:

题目给出 k k k个技能,可以把怪物血量直接变成0,那么我们对怪物数组从小到大排序,然后输出前 n − k n-k nk个的和(因为剩下的怪物只能平A了)。

代码:

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, k, t;
    vector<int> health;
    cin >> n >> k;
    for(int i = 0; i < n; ++i) {
        cin >> t;
        health.push_back(t);
    }
    sort(begin(health), end(health));
    if(k > n) k = n;
    long long tot = accumulate(begin(health), begin(health) + n - k, (long long)0);
    cout << tot <<endl;
    return 0;
}

Problem D:Caracal vs Monster

题目传送门:https://atcoder.jp/contests/abc153/tasks/abc153_d

解题思路:

我们可以将场上所有的怪兽攻击一次计算为一次攻击,推导可得:

为了体力战胜1只H怪兽所需的攻击次数为 f ( H ) f(H) f(H)
f ( H ) = { 2 × f ( ⌊ ( H / 2 ) ⌋ )    ( H > 1 ) 1                          ( H = 1 ) f(H) = \left\{\begin{matrix} 2\times f(\left \lfloor (H/2) \right \rfloor) \ \ (H>1)\\ 1 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (H=1) \end{matrix}\right. f(H)={2×f((H/2))  (H>1)1                        (H=1)
代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
    ll n;
    ll now = 1;
    ll tot = 0;
    cin >> n;
    while(n >= 1) {
        tot += now;
        now <<= 1;
        n /= 2;
    }
    cout << tot << endl;
    return 0;
}

Problem E:Crested Ibis vs Monster

题目传送门:https://atcoder.jp/contests/abc153/tasks/abc153_e

解题思路:

这道题是典型的背包dp模板题,就是完全背包条件下,找大于等于最大容量的最小价值。

定义 d p [ i ] [ j ] dp[i][j] dp[i][j]为前 i i i个咒语造成了 j j j点伤害最少使用的 M P MP MP量,那么状态转移方程为:

d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j ] , d p [ i ] [ m a x ( 0 , j − a [ i ] ) ] + b [ i ] ) dp[i][j] = min(dp[i-1][j], dp[i][max(0,j-a[i])] +b[i]) dp[i][j]=min(dp[i1][j],dp[i][max(0,ja[i])]+b[i])

时间复杂度: O ( M N ) O(MN) O(MN)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 5;
const int M = 2e4 + 5;

int a[N], b[N];
int dp[N][M];

int main()
{
    int h, n;
    cin >> h >> n;
    for(int i = 1; i <= n; ++i) 
        cin >> a[i] >> b[i];
    memset(dp, 0x3f, sizeof dp);
    dp[0][0] = 0;
    for(int i = 1; i <= n; ++i) {
        for(int j = 0; j <= h; ++j) {
            dp[i][j] = min(dp[i - 1][j], dp[i][max(0, j - a[i])] + b[i]);
        }
    }
    cout << dp[n][h] << endl;
    return 0;
}

我们发现,第一维的空间完全可以省略,所以可以简化成如下代码:

d p [ j ] = m i n ( d p [ j ] , d p [ m a x ( 0 , j − a [ i ] ) ] + b [ i ] ) dp[j] = min(dp[j], dp[max(0,j-a[i])] +b[i]) dp[j]=min(dp[j],dp[max(0,ja[i])]+b[i])

即选择下一个技能的话就要加上下一个技能的b[ i ],不选择的话就不加。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3 + 5;
const int M = 2e4 + 5;

int a[N], b[N];
int dp[N];

int main()
{
    int h, n;
    cin >> h >> n;
    for(int i = 1; i <= n; ++i)
        cin >> a[i] >> b[i];
    memset(dp, 0x3f, sizeof dp);
    dp[0] = 0;
    for(int i = 1; i <= n; ++i) {
        for(int j = 0; j <= h; ++j) {
            dp[j] = min(dp[j], dp[max(0, j - a[i])] + b[i]);
        }
    }

    cout << dp[h] << endl;
    return 0;
}

Problem F:Silver Fox vs Monster

题目传送门:https://atcoder.jp/contests/abc153/tasks/abc153_f

解题思路:

n n n个怪物,每个怪物的坐标为 x i x_i xi,血量为 h i h_i hi,在 x x x处施展一次攻击会对 x − d x - d xd x + d x + d x+d区间内的所有怪物造成 A A A点伤害,怪物的血量小于等于0则死亡,问至少攻击多少次能消灭全部怪物。

我们首先对怪物按坐标进行排序。首先,攻击顺序肯定是不重要的,而且最左边的点如果要被消灭的话一定会被攻击 ⌊ H i + A − 1 A ⌋ \lfloor \frac {H_i+A-1} A \rfloor AHi+A1次,把攻击的血量累计到总伤害,然后后面 2 ∗ d 2*d 2d的距离都会受到影响,我们需要知道最近不受伤害的点,这个可以使用双指针算法,也可以使用二分,然后运用差分的思想,构建一个差分数组,把这个坐标的值加扣的血量,每次到一个点我们的总伤害先减去这个差分数组,这样就能维护当前被影响的血量。

这里还可以使用线段树或者树状数组来修改区间,可以当做练手来试试。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 50; // 蜜汁RE,不知道为什么,2e5+10就RE
ll c[N];

struct Node {
    int x, h;
    inline bool operator < (const Node& t) const {
        return x < t.x;
    }
} p[N];

int main()
{
    int n, a, d;
    cin >> n >> d >> a;
    for(int i = 1; i <= n; ++i)
        cin >> p[i].x >> p[i].h;
    sort(p + 1, p + n + 1);
    
    ll ans = 0;
    // 双指针
    for(int i = 1, j = 1; i <= n; ++i) {
        while(j <= n && p[j].x <= p[i].x + 2 * d) ++j;
        ll need = max((p[i].h - c[i] * a + a - 1) / a, 0ll);
        ans += need;
        // 构造差分序列
        c[i] += need;
        c[j] -= need;
        c[i + 1] += c[i];
    }
    cout << ans << endl;
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: atcoder beginner contest 235 是一场由 AtCoder 组织的初学者比赛,旨在为初学者提供一个锻炼自己编程能力的平台。比赛通常包括多个问题,参赛者需要在规定时间内解决这些问题。比赛难度逐渐增加,从而帮助参赛者提高自己的编程技能。 ### 回答2: ATCoder Beginner Contest 235(简称ABC 235)是一项由ATCoder举办的编程竞赛。该比赛旨在为初学者提供一个机会展示他们的编程技巧和解决问题的能力。 ABC 235通常由4个问题组成,题目难度递增。参赛者需要在规定的时间内使用编程语言解决这些问题。这些问题通常涵盖了各种编程相关的主题,例如数学问题、字符串处理、排序和搜索算法等。 在比赛开始前,参赛者将获得一份题目说明文档和输入样例。他们需要根据题目要求编写程序,处理给定的输入数据,并生成相应的输出。比赛时间一般为2-3小时,参赛者需要尽可能快速且准确地解决问题。 评判将根据参赛者的程序输出与预期结果的一致性进行。参赛者可以在比赛过程中提交多次解答,但只有第一次正确答案会被记入最终的成绩。 ABC 235不仅提供了一个竞赛平台,还鼓励参赛者通过讨论和分享解题思路来学习和提高。在比赛结束后,ATCoder将提供详细的解题分析和解题报告,帮助参赛者了解每个题目的最佳解决方法,并提供参考答案和示例代码。 通过参加ATCoder Beginner Contest 235,参赛者可以提升他们的编程技能,锻炼逻辑思维能力,并与全球的编程爱好者交流。无论是初学者还是有经验的编程者,ABC 235都是一个很好的学习和挑战的机会。 ### 回答3: AtCoder Beginner Contest 235 是一个在 AtCoder 上的初级比赛。该比赛通常会吸引很多新手程序员参加。它由 AtCoder 组织主办,旨在帮助新手提高编程技能以及在竞赛中锻炼自己。 比赛的题目难度由易到难,共有四个问题。通常,第一个问题是一个简单的数学问题,要求解决一个简单的算术运算。第二个问题可能是一个字符串操作问题,需要对给定的字符串进行处理。第三个问题可能是一个动态规划或贪心算法问题,需要细心分析问题,找出最优解。最后一个问题通常是一个较难的图论或组合问题,需要一些高级算法来解决。 参赛选手在比赛开始后有一定的时间限制来解决这些问题。他们可以使用自己熟悉的编程语言来实现解决方案。然后他们将自己的程序提交到 AtCoder 的在线评测系统中进行评测。评测结果会即时显示,并将参赛选手的成绩排名和讨论解答过程的视频分享给其他选手。 参加 AtCoder Beginner Contest 235 对于新手来说是一个很好的机会。通过解决这些问题,他们可以练习编程技巧,提高解决问题的能力。比赛结束后,他们还可以看到其他选手的解答,学习他们的思路和方法。同时,比赛的排名和奖励也是一种鼓励和激励新手继续努力学习的方式。 总之,AtCoder Beginner Contest 235 是一个对于新手非常友好的比赛,它提供了一个锻炼和展示编程技能的平台。无论是对于新手还是更有经验的选手,参加这样的比赛都是一个宝贵的机会。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值