1. 程式人生 > 其它 >CF EDU 114 D - The Strongest Build

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;
}