D : Fight with Monsters

题目大意 :

      有一组数,每个值对应着一个怪物的 hp 值,现在有两个人,一个自己一个对手,每个人有一个攻击值,
两个人轮流攻击怪物,如果是自己将怪物先打倒,则 + 1 分,反之则不加,在攻击过程中,自己可以使用
特权,轮到对手的时候自己攻击将怪物打倒,从而使得自己能够加分,特权是有限制的,用完特权后剩下的就只
能听天由命了,问在这种情况下自己最多可以得到多少分 ?

析题得说 :

      我们知道,两个人是轮流进行的,所以我们通过看能进行几轮,最后该自己的时候怪物还剩下多少 hp 值,
如果说剩下的 hp 值我直接就能干死,说明我们不需要使用特权就能 + 1,相反看一下能够使用几次特权
才能将怪物干掉,因为每个数的顺序是不一样的,我们不知道哪个数对应的特权是几次,但是我们知道特权
使用的次数越少,我们就能得到更高的分,比如一个数需要使用一次特权,一个需要使用两次,那我们肯定
先处理哪个一次特权的数,所以我们可以将所有怪物需要干掉所使用的特权排个序,,然后最后累加处理
即可。

求每个怪物被干掉所需要的特权次数 ?

     我是通过 特判 + 循环去模拟,数据多了显然一个一个循环处理肯定会超时,果不其然,在第42个样例的时候就超时
了,然后各种缩减,还是超时,不行了,所以看了一下大佬的,才发现自己是真的菜,没有转过弯将循环算去弄成一个
式子进行处理,这样就铁定不会超时了.
我们最后求的是特权,实际上就是需要多少次 自己的攻击值可以干掉怪物,那直接除一下不就知道需要几次了,但是
这里的时候由于前面都是一对一对,到这里的时候还包括我不用使用特权,也可以干掉 a 点 hp 值,所以这里就需要
我们 (取余得到的结果 / a ) 向上取整 - 1 就是所需要的特权了,另外 余数 = 0 的时候我们需要特殊处理,因
为这里并不是自己能够加分,所以我们可以向前轮回一圈,使得余数是 a + b,然后看需要几次特权处理,与余数不是
0 的道理类似。

为什么向上取整而不是向下取整 ?

     看一下第一个样例 :
6 2 3 3
7 10 50 12 1 8
a = 2,b = 3
如果我们最后对 a + b 取余得到的是 4,我们向下取整 4 / 2 = 2,因为还包含一个自己,所以还需要 - 1
但是如果取余得到的 3 ,向下取整 3 / 2 = 1,同样也包含一个自己, 也需要 - 1,这时候答案是 0,但实际
上使用特权的次数 是 1,所以向下取整不可取.
我们试一下向上取整, 3 / 2 向上取整 得到的 是 2, - 1 得到是 1,合适。

Code :

先看一下我的循环模拟吧,哈哈,思路大体一样,主要是处理特权次数的方式不同。

#include <map>
#include <cstdio>
#include <iostream> using namespace std; const int maxn = 2e5 + 10;
int mon[maxn]; map<int,int>cnt;
map<int,int>::iterator it; int n,a,b,k;
int res = 0; int main(void) {
scanf("%d%d%d%d",&n,&a,&b,&k);
res = 0;
for(int i = 1; i <= n; i ++) {
scanf("%d",&mon[i]);
int count = 0;
if(mon[i] <= a) res ++; // 本身就 <= a ,可以直接干掉
else {
int m = a + b;
int MOD = mon[i] % m;
if(MOD <= a && MOD != 0) { // 下一个就是自己出手,也可以直接干掉
res ++;
} else if(MOD != 0 && k != 0) { // 余数不为 0 的时候
int ans = a;
while(MOD > ans) { // 模拟,哈哈,可以直接计算的
ans = ans + a;
count ++;
}
if(count == 1) {
k --;
res ++;
continue;
}
if(count > k) continue;
cnt[count] ++; } else if(MOD == 0 && k != 0) {
int ans = 0;
count = 0;
while(a * ans < b) { // 同上
count ++;
ans ++;
}
if(count == 1) {
k --;
res ++;
continue;
}
if(count > k) continue;
cnt[count] ++;
}
}
}
for(it = cnt.begin(); it != cnt.end(); it ++) { // 最后的处理
int size = k / it->first;
if(size >= it -> second) {
res += it -> second;
k -= it->second;
} else {
res += size;
break;
}
}
printf("%d\n",res);
return 0;
}

贪心代码:

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = 2e5 + 10; int a[maxn],cnt[maxn];
int n,x,b,k; int main(void) {
scanf("%d%d%d%d",&n,&x,&b,&k);
int MOD = x + b;
for(int i = 1; i <= n; i ++ ){
scanf("%d",&a[i]);
a[i] = a[i] % MOD;
if(a[i] == 0) a[i] += x + b;
a[i] = (a[i] + x - 1) / x - 1; // 向上取整,减 1 是因为本来就该自己了,减去本身
}
sort(a + 1,a + 1 + n);
int res = 0;
for(int i = 1; i <= n; i ++) {
if(a[i] == 0) ++ res;
else if(a[i] <= k) {
++ res;
k -= a[i];
} else {
break;
}
}
cout << res << endl;
return 0;
}

通过这道题,Get 那些干货 ?

    1、贪心就是找到其根本,想的东西全面一点,然后尝试着去看能不能推翻现有的结论。
2、能通过一个式子进行计算的就最后不要去模拟,寻找更有效的方法,还是抓其本质。
3、向上取整 : (a + b - 1) / b (减 - 是为了避免整除出现的问题)
向下取整 : a / b
四舍五入 :(a + b / 2)/ b
注意 : 负数可不一样哦
⌊59/60⌋=0 ⌈59/60⌉=1 ⌊-59/60⌋=-1 ⌈-59/60⌉=0

Codeforces Round #617 (Div. 3) D. Fight with Monsters的更多相关文章

  1. Codeforces Round #617 (Div. 3) 补题记录

    1296A - Array with Odd Sum 题意:可以改变数组中的一个数的值成另外一个数组中的数,问能不能使数组的和是个奇数 思路:签到,如果本来数组的和就是个奇数,那就OK 如果不是,就需 ...

  2. Codeforces Round #617 (Div. 3) 题解

    又是隔了一年才来补题的我 A.B水题就不用说了 C - Yet Another Walking Robot C题我居然卡了一会,最后决定用map水,结果出来看了看题解,居然真的是map...没想到会出 ...

  3. [CF百场计划]Codeforces Round #617 (Div. 3)

    A. Array with Odd Sum Description You are given an array \(a\) consisting of \(n\) integers. In one ...

  4. Codeforces Round #278 (Div. 1) A. Fight the Monster 暴力

    A. Fight the Monster Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/487/ ...

  5. Codeforces Round #617 (Div. 3) String Coloring(E1.E2)

    (easy version): 题目链接:http://codeforces.com/contest/1296/problem/E1 题目一句话就是说,两种颜色不同的字符可以相互换位, 问,对这字符串 ...

  6. Codeforces #617 (Div. 3) D. Fight with Monsters(贪心,排序)

    There are nn monsters standing in a row numbered from 11 to nn . The ii -th monster has hihi health ...

  7. Codeforces Round #617 (Div. 3)F. Berland Beauty

    题意: 给一棵树,边权未知,现在给m组约束,每组约束给出从u到v路径中的最小值,现在让你给出一组边权,使得符合之前的约束,不能给出输出-1 思路: 因为n较小,对于每组约束我们可以直接暴力修改路径上的 ...

  8. Codeforces Round #617 (Div. 3)

    A 题意:能否将数组里面的值用数组里面的值替换出一个和为奇数的数组 思路:1.和为奇数yes 2.和为偶数但有奇数yes 3.个数是奇数的,有奇数的yes 其他都是no 果然罚时全给了A #inclu ...

  9. Codeforces Round #617 (Div. 3)A. Array with Odd Sum(水题)

    You are given an array aa consisting of nn integers. In one move, you can choose two indices 1≤i,j≤n ...

随机推荐

  1. 一个C#开发者重温Java的心路历程

    前言 我们都知道软件开发是工科,不是理科:本质上和电工.钳工是一样的. 也就是说,软件技术成长也与电工.钳工的技术成长是一样的,靠的是练,而不是学. 所以,很多时候,我们称应届大学生是一张白纸,啥也不 ...

  2. CI框架获取post和get参数_CodeIgniter使用心得

    请参考:CI文档的输入类部分: $this->input->post()$this->input->get() -------------------------------- ...

  3. 金三银四,磨砺锋芒;剑指大厂,扬帆起航(2020年最全大厂WEB前端面试题精选)上

    金三银四,磨砺锋芒:剑指大厂,扬帆起航(2020年最全大厂WEB前端面试题精选)上 引言 元旦匆匆而过,2020年的春节又接踵而来,大家除了忙的提着裤子加班.年底冲冲冲外,还有着对于明年的迷茫和期待! ...

  4. .Net Core 导出Html到PDF

    前言 最近由于项目的需求问题,涉及到了在.Net Core中导出PDF的一个问题,最后选择方式是后端拼接到Html页面然后再通过Html导出到PDF.中间也尝试了许多的NuGet包.但是并不如意,可用 ...

  5. WiFi模块Demo(新手教程)图文详解模块使用教程

    本文出自APICloud官方论坛,感谢论坛版主 Mr.ZhouHeng 的分享. 第一步我们需要在开发控制台创建一个Native App应用以及添模块的准备工作: 按照下图步骤 输入完点创建完成之后 ...

  6. Node: 使用nrm管理npm源

    一.简介 npm是一款非常好用的包管理工具,在前端开发中很多时候都会使用npm安装其他包文件.但是,npm安装某些包时有时会安装地很慢,这是因为npm管理的源中有些是国外的,包下载的时候需要花费很多时 ...

  7. rdlc报表输入中文出现小方块

    在用vs自带的报表文件的时候,在输入中文的时候,会出现一些小方块. 百度到的资料:当然我试了下,没有用. 用文本编辑器(我用的是editplus)打开需要批量处理的rdlc文件. 将所有 <St ...

  8. max count混合使用

    SELECT MAX(a1.人数) FROM (SELECT COUNT(category_id) AS "人数",category_id FROM course_category ...

  9. KD-tree 学习小记

    考 \(NOI\) 时不会,感觉很亏.于是学了一上午,写了一晚上. 感觉这东西就是个复杂度玄学的高级暴力 (大雾 KD-tree 基本信息 \(D\) 就是 \(Dimension\) ,维度的意思. ...

  10. [bzoj1005] [洛谷P2624] 明明的烦恼

    Description 自从明明学了树的结构,就对奇怪的树产生了兴趣-- 给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树? Input 第一行为N(0 ...