《算法竞赛进阶指南》-AcWing-998. 起床困难综合症-题解

Posted Tisfy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法竞赛进阶指南》-AcWing-998. 起床困难综合症-题解相关的知识,希望对你有一定的参考价值。

起床困难综合症

传送门

题目描述

为了打败起床困难综合症去打败睡眠boss,boss有 n n n扇防御门,每扇门包含一个运算符( O R 、 X O R 、 A N D OR、XOR、AND ORXORAND)和一个运算数(非负整数),攻击经过这扇门后将与门进行相应的运算操作。

勇士的初始攻击力只能是 [ 0 , m ] [0,m] [0,m]之间的一个整数,门及其摆放是固定的,勇士想通过合适的攻击以对boss照成最大的伤害。

输入样例

3 10
AND 5
OR 6
XOR 7

解释:一共 3 3 3扇门,初始攻击在 0 0 0~ 10 10 10之间,第一扇门将与攻击和5进行与运算,第二扇将第一扇运算后的结果与6进行或操作,最后一扇门将前面的结果与7进行异或。

样例输出

1

解释:假设初始攻击力为 4 ( 0 ≤ 4 ≤ 10 ) 4(0\\leq4\\leq10) 4(0410),则经过如下运算:

4 AND 5 = 4
4 OR 6 = 6
6 XOR 7 = 1

获得最终攻击力为1。在 0 0 0~ 10 10 10中找不到另外一个数使得最终运算的结果大于 1 1 1

解题思路

攻击力的每一位与另一位互不影响。 1 0 9 10^9 109的数据不超过 30 30 30位。

我们只需要分别看每一位(0和1两种情况),如果这一位是 1 1 1通过所有门后将会变成什么、如果是 0 0 0又会变成什么。

  • 当然,我们希望最终攻击尽可能大,这就需要我们先从高位开始计算;
  • 我们希望初始攻击尽可能小(需要不超过 m m m),这就需要满足以下两个条件时才让这一位的初始攻击力为 1 1 1
    • 这一位初始为 1 1 1的最终攻击力大于初始为 0 0 0的最终攻击力
    • 这一位初始为 1 1 1的话目前初始攻击力不超过最大攻击力 m m m

更多解释请见代码注释


AC代码

#include <bits/stdc++.h>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a))
#define dbg(x) cout << #x << " = " << x << endl
#define fi(i, l, r) for (int i = l; i < r; i++)
#define cd(a) scanf("%d", &a)
typedef long long ll;
string op[100010];
int num[100010];
int n;
int calculate(int wei, int thisBit) // 计算初始攻击的第wei位初始值位thisBit时,通过所有门后的最终攻击力
{
    for(int i=0;i<n;i++) // 每扇门
    {
        int thisBit2=num[i]>>wei&1; // 取出这扇门的操作数的这一位
        if(op[i]=="AND")thisBit&=thisBit2; // 如果这扇门的AND,就做与运算
        else if(op[i]=="OR")thisBit|=thisBit2; // OR就做或运算
        else thisBit^=thisBit2; // 否则异或运算
    }
    return thisBit; // 返回这一位经过所有门后最终的值
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int m;
    cin>>n>>m;
    for(int i=0;i<n;i++)
        cin>>op[i]>>num[i];
    int ans=0, original=0;
    for(int i=29;i>=0;i--) // 从大到小分析每一位
    {
        int one=calculate(i, 1); // 如果这一位的初始攻击力是1,最终攻击力将会是one
        int zero=calculate(i, 0); // 如果这一位的初始攻击力是0,最终攻击力将会是zero
        if(original+(1<<i)<=m&&one>zero) // 如果这一位为1的话初始攻击力<=m 并且 这一位为1的话最终攻击力大于这一位为0的话的最终的攻击力
            original+=1<<i, ans+=one<<i; // 那么这一位初始攻击力设为1,初始攻击力加上这一位,最终攻击力加上这一位为1的时候产生的最终攻击力one
        else
            ans+=zero<<i; // 否则这一位初始攻击力为0,最终攻击力加上这一位初始值为0的时候产生的最终的攻击力zero
    }
    cout<<ans<<endl; // 输出答案
    return 0;
}

原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/119220647

以上是关于《算法竞赛进阶指南》-AcWing-998. 起床困难综合症-题解的主要内容,如果未能解决你的问题,请参考以下文章

《算法竞赛进阶指南》1.8总结与练习

题解|《算法竞赛进阶指南》 Sticks

实验13读后感:《算法竞赛进阶指南》

《算法竞赛进阶指南》图论习题

算法竞赛进阶指南做题记录

算法竞赛进阶指南基本算法:递推与递归