Loading [MathJax]/jax/output/CommonHTML/jax.js

2016级算法期末上机-F.中等·AlvinZH's Fight with DDLs II

1118 AlvinZH's Fight with DDLs II

思路

中等题,贪心。

理解题意,每次攻击中,可以使某个敌人生命值-1,自己生命值减去∑存活敌人总攻击力。

贪心思想,血量少攻击高的要先消灭,所以以A/L作为参数排序,即将所有的敌人根据A/L从大到小排序。

遍历一次,对于排序好的敌人,HP减去(总攻击*该敌人血量),总攻击减去该敌人攻击。代码如下:

HP -= (sumA * H[i].L);
sumA -= H[i].A;
if(HP <= 0) break;

分析

贪心证明:对于已经排好序的序列,HP总消耗为 ni=1nj=i(H[i].LH[j].A)

如果我们交换其中相邻两个的位置,位置设为x,y,HP消耗与原来相比,有影响的也只有i=x和i=y两项,原来是 H[x].Lnj=xH[j].A+H[y].Lnj=yH[j].A ,而现在变成了H[y].Lnj=xH[j].A+H[x].L(H[x].A+nj=y+1H[j].A) ,其他未变,后者减去前者,得到H[y].LH[x].AH[x].LH[y].A ,依照排序来看,有 H[x].AH[x].LH[y].AH[y].L ,所以后者减去前者的值是大于等于0的。

由此可以证明:如果相邻两个交换,会导致HP总消耗增加。任何的一个攻击敌人次序,都可以在已排好序的次序上通过多次上述交换(相邻,且索引值小的后移)得到,由此可以判断所有的攻击次序HP消耗值都大于等于原排序攻击次列。

贪心得证,至于如何多次交换,可参考冒泡排序过程。

时间复杂度:O(nlgn)。

空间复杂度:O(n)。

参考代码

/* 
 Author: 朱辉(35)
 Result: AC	Submission_id: 514527
 Created at: Mon Dec 25 2017 03:09:00 GMT+0800 (CST)
 Problem: 1118	Time: 4	Memory: 2840
*/

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;

struct Hero {
    int A, L;
    bool operator < (const Hero h) const {
        return 1.0 * A/L > 1.0 * h.A/h.L;
    }
};

int n, HP;
Hero H[1005];

int main()
{
    while(~scanf("%d %d", &n, &HP))
    {
        int sumA = 0;//总攻击力
        for (int i = 0; i < n; ++i) {
            scanf("%d %d", &H[i].A, &H[i].L);
            sumA += H[i].A;
        }

        sort(H, H+n);

        for (int i = 0; i < n; ++i) {
            HP -= (sumA * H[i].L);
            sumA -= H[i].A;
            if(HP <= 0) break;
        }

        if(HP > 0) printf("YES\n");
        else printf("NO\n");
    }
}
posted @   AlvinZH  阅读(588)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示