CF EDU 114 D - The Strongest Build
D - The Strongest Build
BFS + 优先队列 + 哈希
将被 ban 掉的策略存到 map 里,一开始将最大的策略放入优先队列中,每次取队首策略是否被 ban 掉了,如果没有当前策略就是答案
如果被 ban 掉了,那放入比该策略小一点的策略,设队首策略为 \(b_1,b_2,b_3,...,b_n\)
则分别放入 \(b_1-1,b_2,...,b_n\), \(b_1, b_2-1,...,b_n\) ... , \(b_1,b_2,...,b_n-1\)
再开一个 map 维护每个策略是否被放进过优先队列中,如果被放进去过就不再放
极限情况下前 \(m\) 大的都被 ban 了,每次转移的复杂度为 \(n\), 复杂度为 \(n*m*log(n*m)\)
注意重载结构体小于号与结构体初始化的细节(把没用到的地方都赋 0)
本题可用 map 来判断某个策略是否被 ban 或已经放入队列过,也可以用下述的哈希函数表示策略
ull hs(vector<int> &vt)
{
ull ans = 0, p = 1;
for (auto i : vt)
{
ans += p * i;
p *= mod;
}
return ans;
}
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <tuple>
#include <map>
#include <queue>
using namespace std;
typedef long long ll;
struct Node
{
ll val;
int b[12];
bool operator<(const Node &x) const
{
if (val != x.val)
return val < x.val;
for (int i = 0; i < 12; i++)
{
if (b[i] != x.b[i])
return b[i] < x.b[i];
}
return false;
}
};
map<Node, bool> st, ban;
priority_queue<Node> heap;
int n, m;
const int N = 2e5 + 10;
ll a[12][N];
int d[12];
void print(Node &x)
{
cout << x.val << endl;
for (int i = 0; i < 12; i++)
cout << x.b[i] << " ";
cout << endl;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
int k;
scanf("%d", &k);
d[i] = k;
for (int j = 1; j <= k; j++)
scanf("%lld", &a[i][j]);
}
scanf("%d", &m);
while(m--)
{
Node now;
ll sum = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &now.b[i]);
sum += a[i][now.b[i]];
}
now.b[0] = 0;
for (int i = n + 1; i < 12; i++)
now.b[i] = 0;
now.val = sum;
// print(now);
ban[now] = true;
}
Node first;
first.val = 0;
for (int i = 1; i <= n; i++)
{
first.b[i] = d[i];
first.val += a[i][d[i]];
}
first.b[0] = 0;
for (int i = n + 1; i < 12; i++)
first.b[i] = 0;
// print(first);
heap.push(first);
while(!heap.empty())
{
auto fr = heap.top();
heap.pop();
if (!ban.count(fr))
{
for (int i = 1; i <= n; i++)
printf("%d ", fr.b[i]);
printf("\n");
return 0;
}
for (int i = 1; i <= n; i++)
{
Node next = fr;
int id = next.b[i];
if (id > 1)
{
next.val += a[i][id-1] - a[i][id];
next.b[i] = id - 1;
if (st.count(next))
continue;
st[next] = true;
heap.push(next);
}
}
}
return 0;
}