本文已参与「新人创作礼」活动,一起开启掘金创作之路。
@TOC
起床困难综合症
题目描述
为了打败起床困难综合症去打败睡眠boss,boss有扇防御门,每扇门包含一个运算符()和一个运算数(非负整数),攻击经过这扇门后将与门进行相应的运算操作。
勇士的初始攻击力只能是之间的一个整数,门及其摆放是固定的,勇士想通过合适的攻击以对boss照成最大的伤害。
输入样例
3 10
AND 5
OR 6
XOR 7
解释:一共扇门,初始攻击在~之间,第一扇门将与攻击和5进行与运算,第二扇将第一扇运算后的结果与6进行或操作,最后一扇门将前面的结果与7进行异或。
样例输出
1
解释:假设初始攻击力为,则经过如下运算:
4 AND 5 = 4
4 OR 6 = 6
6 XOR 7 = 1
获得最终攻击力为1。在~中找不到另外一个数使得最终运算的结果大于。
解题思路
攻击力的每一位与另一位互不影响。 且的数据不超过位。
我们只需要分别看每一位(0和1两种情况),如果这一位是通过所有门后将会变成什么、如果是又会变成什么。
- 当然,我们希望最终攻击尽可能大,这就需要我们先从高位开始计算;
- 我们希望初始攻击尽可能小(需要不超过),这就需要满足以下两个条件时才让这一位的初始攻击力为:
- 这一位初始为的最终攻击力大于初始为的最终攻击力
- 这一位初始为的话目前初始攻击力不超过最大攻击力
更多解释请见代码注释
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;
}
同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:letmefly.blog.csdn.net/article/det…