首页 > 其他分享 >20221113_T2A_背包贪心

20221113_T2A_背包贪心

时间:2022-11-13 22:11:25浏览次数:49  
标签:T2A 20221113 mid Steve int 猎人 read 怪物 贪心

题意

Steve 的城堡正在被大量的怪物袭击。
共有 \(n\) 个怪物正在袭击城堡,第 \(i\) 个怪物的攻击力为 \(a_i\),防御力为 \(b_i\)。城内有 \(m\) 个怪物猎人,第 \(j\) 个怪物猎人的生命值为 \(h_j\)。猎人可以和怪物对战,当猎人和第 \(i\) 个怪物对战时,猎人需要消耗连续的 \(b_i\) 秒时间攻击怪物,这段时间怪物也会攻击猎人,使猎人每秒初减少 \(a_i\) 的生命值。一旦猎人的生命值小于或等于猎人就会死亡无法继续对战。若猎人未死亡,则 bi 秒之后该怪物即被猎人消灭。这些怪物有一个超能力:每当一个怪物被消灭后,其余的所有怪物的攻击力和防御力都会增加 \(d\)。由于请猎人作战的费用十分昂贵,Steve 打算请一个猎人消灭尽可能多的怪物。
当然,Steve 可以自由决定猎人以何顺序消灭哪些怪物。Steve 想知道,对于每一个猎人求出最多能消灭多少个怪物。

题解

赛时得分: 0/100/100

我们从小情况入手,假如说现在有两个怪物,我知道两个都要选择了,那么我应该用什么顺序选择?

不妨令两个怪物分别是 \(a_1,b_1\),\(a_2,b_2\)。

反正肯定是一个要 \(+d\) 的吗,我们假设我们选择 \(a_1,b_1\) 在前,看看他要满足什么条件。

那么就是 \(a_1b_1+(a_2+d)\times(b_2+d) \leq a_2b_2+(a_1+d)\times(a_1+d)\)

移项 \((a_2+b_2)d \leq (a_1+a_2)d\)。

我们发现我们一定会选择 \(a+b\) 大的东西在前面。

既然确定了选择顺序,我们排序之后做一个 \(\mathcal{O}(n^2)\) 的背包,然后询问的时候就用最后一个背包二分就好了。

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
template <typename T>inline void read(T& t){t=0; register char ch=getchar(); register int fflag=1;while(!('0'<=ch&&ch<='9')) {if(ch=='-') fflag=-1;ch=getchar();}while(('0'<=ch&&ch<='9')){t=t*10+ch-'0'; ch=getchar();} t*=fflag;}
template <typename T,typename... Args> inline void read(T& t, Args&... args) {read(t);read(args...);}
const int N = 3e3 + 10, inf = 0x3f3f3f3f;

struct Info {
    int x, y;
    bool operator < (const Info &info) const {
        return x + y > info.x + info.y;
    }
}a[N];
int n, m, d;
int dp[N][N], ne[N];
bool used[N];

signed main() {
    freopen("hunter.in", "r", stdin);
    freopen("hunter.out", "w", stdout);
    read(n, m, d);
    for(int i = 1; i <= n; ++i) read(a[i].x);
    for(int i = 1; i <= n; ++i) read(a[i].y);
    sort(a + 1, a + n + 1);
    memset(dp, 0x3f, sizeof(dp));
    dp[0][0] = 0;
    for(int i = 1; i <= n; ++i) {
        dp[i][0] = 0;
        for(int j = 1; j <= i; ++j) dp[i][j] = min(dp[i - 1][j - 1] + (a[i].x + (j - 1) * d) * (a[i].y + (j - 1) * d), dp[i - 1][j]);
    }
    for(int i = 1; i <= n; ++i) ne[i] = dp[n][i];
    for(int i = 1; i <= m; ++i) {
        int hp;
        read(hp);
        int l = 0, r = n;
        while(l < r) {
            int mid = l + r + 1 >> 1;
            if(ne[mid] >= hp) r = mid - 1;
            else l = mid;
        }
        printf("%d ", l);
    }
    return 0;
}
// 55 65
// 105 30

标签:T2A,20221113,mid,Steve,int,猎人,read,怪物,贪心
From: https://www.cnblogs.com/Mercury-City/p/16887146.html

相关文章

  • L10U5-3 Dealing with an employee's problem 20221113
    ExpressionsProblemsbehaviorDescribingproblembehavioronthejobUsetheseexpressionstoaskaboutanddescribeproblembehavioronthejob.A.What'sup?......
  • 20221113_T1A-_并查集
    题意在一个文件目录下有\(n\)个不同的文件,每个文件都有一个文件名,其中第\(i\)个文件的文件名为\(s_i\)。这些文件名两两不同。小C希望更改一部分文件的文件名,他......
  • 20221113 star模拟赛 随记
    Explo依次考虑是否取\(n\)个物品,初始有权值\(p=w\),以及常数\(k,c\)。物品分为两类,对于第\(i\)个物品:若为第一类,则选择第\(i\)个物品会得到\(a_i\timesp\)的......
  • L10U4-4 Closing a presentation 20221113
    1ReadingEffectiveconclusionsUsingsubheadingstounderstandatextAtextusuallyhasatitle(title),butwritersoftenaddsubheadings(subheadings)too......
  • 代码随想录训练营第三十一天 | 贪心算法
    贪心算法的核心思想是在每一步决策中都找到局部最优解122.买卖股票的最佳时机classSolution{publicintmaxProfit(int[]prices){intn=prices.le......
  • 贪心
    455.分发饼干假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子i,都有一个胃口值g[i],这是能让孩子们满足胃口的饼干的......
  • 20221007_T1A-_贪心/树形dp
    题意给定一个树,求经过\(k\)个不同点所需要的步骤。以及给出一个方案。题解赛时得分:5/100不知道赛时哪里写错了。能想到找出以1开始的直径,直径上的点是必定会走的......
  • 【UOJ 494】DNA序列(贪心)(Lyndon分解)
    DNA序列题目链接:UOJ494题目大意给你n个字符串,要你每个都选一段非空前缀按某种顺序拼在一起使得形成的大字符串字典序最小。思路假设如果知道插入的顺序,我们要怎么......
  • 贪心算法_Leetcode刷题_7/100
    贪心算法采用贪心策略,保证每次操作是局部最优的,从而使随后结果是全局最优的。455.分配饼干贪心策略:尽量把最小的饼干分配给胃口最小的孩子。我的代码:算法描述:将......
  • Great Sequence (CF2,C) (贪心)
    思路:最后转化成一个链,然后贪心地从链的一端处理即可! #include<bits/stdc++.h>usingnamespacestd;#defineM2000005#defineriregisterintlonglo......