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;
}
posted @ 2022-05-15 15:45  hzy0227  阅读(26)  评论(0编辑  收藏  举报