【#|【牛客】牛客练习赛67-E-牛妹游历城市——位运算优化】题面链接
大致题意 给出n n n 个节点的权值,如果两个点的权值a n d and and 的结果不为0 0 0 则认为这两个点之间有边相连,且边权为l o w b i t ( a & b ) lowbit(a \& b) lowbit(a&b) 求问从1 1 1 走到n n n 点,最短路径为多少
分析
首先不能暴力 因为点数有1 0 5 10^5 105 个,所有可能的边的数量为1 0 5 ? ( 1 0 5 ? 1 ) / 2 ≈ 1 0 10 10^5 * (10^5-1) / 2 \approx 10^{10} 105?(105?1)/2≈1010
考虑位运算优化 我们准备出 32 个组,对于每一个值,如果这个值a a a 在位置i i i 上有值,即a & ( 1 < < i ) ≠ 0 a \& (1 << i ) \neq 0 a&(1<
对于每个组,我们再定义一个变量表示到达组i i i 中的值需要的边权价值t t t, t ≥ ( 1 < < i ) t \geq (1 << i) t≥(1<
对于起点1 1 1 ,我们考虑它的每一个位,如果位i i i 上有值,则认为到达这个位置的组中的其他所有值需要花费( 1 < < i ) (1 << i) (1<
最后考虑最终点的每一位,找出花费最少的位并输出即可
注意特判起点和终点相同的时候
AC code
#include using namespace std;
typedef long long ll;
// NOLINTNEXTLINE
ll lowBit(ll x) { return x & (-x);
}void solve() {
ll _;
cin >> _;
for (ll ts = 0;
ts < _;
++ts) {
ll n;
cin >> n;
vector data[40];
vector cost(40, LONG_LONG_MAX);
vector a(n);
for (ll i = 0;
i < n;
++i) {
cin >> a[i];
for (ll j = 0;
j < 40;
++j)
// NOLINTNEXTLINE
if (a[i] & (1ll << j))
data[j].push_back(i);
}
if (n == 1) {
cout << 0 << endl;
continue;
}
queue q;
for (ll i = 0;
i < 40;
++i) {
// NOLINTNEXTLINE
if (a[0] & (1ll << i)) {
q.push(i);
// NOLINTNEXTLINE
cost[i] = 1ll << i;
}
}while (!q.empty()) {
ll cur = q.front();
q.pop();
for (auto item : data[cur]) {
for (ll i = 0;
i < 40;
++i) {
// NOLINTNEXTLINE
if ((a[item] & (1ll << i)) && cost[i] > (1ll << i) + cost[cur]) {
q.push(i);
// NOLINTNEXTLINE
cost[i] = (1ll << i) + cost[cur];
}
}
}
}ll ans = LONG_LONG_MAX;
for (ll i = 0;
i < 40;
++i) {
// NOLINTNEXTLINE
if (a[n - 1] & (1ll << i)) {
ans = min(ans, cost[i]);
}
}if (ans == LONG_LONG_MAX)
cout << "Impossible" << endl;
else
cout << ans << endl;
}
}signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed localTestCount = 1, localReadPos = cin.tellg();
char localTryReadChar;
do {
if (localTestCount > 20)
throw runtime_error("Check the stdin!!!");
auto startClockForDebug = clock();
solve();
auto endClockForDebug = clock();
cout << "Test " << localTestCount << " successful" << endl;
cerr << "Test " << localTestCount++ << " Run Time: "
<< double(endClockForDebug - startClockForDebug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (localReadPos != cin.tellg() && cin >> localTryReadChar && localTryReadChar != '$' &&
cin.putback(localTryReadChar));
#else
solve();
#endif
return 0;
}
推荐阅读
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)
- 数据结构和算法|LeetCode 的正确使用方式
- #|7.分布式事务管理
- #|算法设计与分析(Java实现)——贪心算法(集合覆盖案例)
- #|算法设计与分析(Java实现)—— 动态规划 (0-1 背包问题)
- #|阿尔法点亮LED灯(一)汇编语言
- #|Multimedia
- #|ARM裸机开发(汇编LED灯实验(I.MX6UL芯片))
- 基础课|使用深度优先搜索(DFS)、广度优先搜索(BFS)、A* 搜索算法求解 (n^2 -1) 数码难题,耗时与内存占用(时空复杂度)对比(附((n^2 - 1) 数码问题控
- #|学习笔记 | Ch05 Pandas数据清洗 —— 缺失值、重复值、异常值