Loading

Educational Codeforces Round 114 (Rated for Div. 2) D. The Strongest Build(优先队列/BFS/Hash/记忆化)

Ivan is playing yet another roguelike computer game. He controls a single hero in the game. The hero has 𝑛n equipment slots. There is a list of 𝑐𝑖ci items for the 𝑖i-th slot, the 𝑗j-th of them increases the hero strength by 𝑎𝑖,𝑗ai,j. The items for each slot are pairwise distinct and are listed in the increasing order of their strength increase. So, 𝑎𝑖,1<𝑎𝑖,2<⋯<𝑎𝑖,𝑐𝑖ai,1<ai,2<⋯<ai,ci.

For each slot Ivan chooses exactly one item. Let the chosen item for the 𝑖i-th slot be the 𝑏𝑖bi-th item in the corresponding list. The sequence of choices [𝑏1,𝑏2,…,𝑏𝑛][b1,b2,…,bn] is called a build.

The strength of a build is the sum of the strength increases of the items in it. Some builds are banned from the game. There is a list of 𝑚m pairwise distinct banned builds. It's guaranteed that there's at least one build that's not banned.

What is the build with the maximum strength that is not banned from the game? If there are multiple builds with maximum strength, print any of them.

Input

The first line contains a single integer 𝑛n (1≤𝑛≤101≤n≤10) — the number of equipment slots.

The 𝑖i-th of the next 𝑛n lines contains the description of the items for the 𝑖i-th slot. First, one integer 𝑐𝑖ci (1≤𝑐𝑖≤2⋅1051≤ci≤2⋅105) — the number of items for the 𝑖i-th slot. Then 𝑐𝑖ci integers 𝑎𝑖,1,𝑎𝑖,2,…,𝑎𝑖,𝑐𝑖ai,1,ai,2,…,ai,ci (1≤𝑎𝑖,1<𝑎𝑖,2<⋯<𝑎𝑖,𝑐𝑖≤1081≤ai,1<ai,2<⋯<ai,ci≤108).

The sum of 𝑐𝑖ci doesn't exceed 2⋅1052⋅105.

The next line contains a single integer 𝑚m (0≤𝑚≤1050≤m≤105) — the number of banned builds.

Each of the next 𝑚m lines contains a description of a banned build — a sequence of 𝑛n integers 𝑏1,𝑏2,…,𝑏𝑛b1,b2,…,bn (1≤𝑏𝑖≤𝑐𝑖1≤bi≤ci).

The builds are pairwise distinct, and there's at least one build that's not banned.

Output

Print the build with the maximum strength that is not banned from the game. If there are multiple builds with maximum strength, print any of them.

Examples

input

Copy

3
3 1 2 3
2 1 5
3 2 4 6
2
3 2 3
3 2 2

output

Copy

2 2 3 

input

Copy

3
3 1 2 3
2 1 5
3 2 4 6
2
3 2 3
2 2 3

output

Copy

1 2 3

input

Copy

3
3 1 2 3
2 1 5
3 2 4 6
2
3 2 3
2 2 3

output

Copy

3 2 2

input

Copy

4
1 10
1 4
1 7
1 3
0

output

Copy

1 1 1 1 

一个很显然的思想就是先找到最大的build,如果被ban的话就依次尝试把每个槽调小1然后再看是否被ban...这可以用优先队列(按照和的大小从大到小排序)+bfs实现。判断是否被ban则可以用hash的思想,因为n最大只有10,所以可以把每组ban构造成一个vector然后在map中标记。仅仅这样还是不行的,因为会有很多重复的状态,这时就需要记忆化了。特别需要注意的是,记忆化时map的键一定要是vector而不能是整个bfs的节点!

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
int n, m, c[200005];
vector<int> v[200005];
map<vector<int>, bool> mp;
struct node {
	vector<int> num;
	int sum;
	bool operator < (const node& o) const {
		return sum < o.sum;
	}
};
map<vector<int>, bool> vis;
priority_queue<node> q;

int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		int cc;
		cin >> cc;
		c[i] = cc;
		for(int j = 1; j <= cc; j++) {
			int a; 
			cin >> a;
			v[i].pb(a);
		}
	}
	cin >> m;
	for(int i = 1; i <= m; i++) {
		vector<int> tmp;
		for(int j = 1; j <= n; j++) {
			int b;
			cin >> b;
			tmp.pb(b);
		}
		mp[tmp] = 1;
	}
	node start;
	start.sum = 0;
	for(int i = 1; i <= n; i++) {
		start.num.pb(c[i]);
		
		start.sum += v[i][c[i] - 1];
	}
	q.push(start);
	while(q.size()) {
		node now = q.top(); q.pop();
		if(vis.find(now.num) != vis.end()) continue;
		vis[now.num] = 1;//注意这里不能用vis[now]来判断
		//结构体和vector的判等区别?
		if(mp.find(now.num) != mp.end()) {
			for(int i = 0; i < n; i++) {
				node nxt = now;
				nxt.sum -= v[i + 1][nxt.num[i] - 1];
				if(nxt.num[i] != 1) nxt.num[i]--;
				nxt.sum += v[i + 1][nxt.num[i] - 1];
				q.push(nxt);
			}
		} else {
			for(auto x : now.num) {
				cout << x << " ";
			}
			break;
		}
	}
	return 0;
}
posted @ 2021-09-22 10:53  脂环  阅读(54)  评论(0编辑  收藏  举报