CF1574 D. The Strongest Build(BFS+剪枝)
目录
Description
有 \(n\) 种卡片,每种卡片选一张,有 \(m\) 种选择是不可以被选的,输出卡片总和最大的选择
State
\(1<=n<=10\)
\(1<=ci<=2*10^5\)
\(1<=a_{i1}<=a_{i2}<=...a_{ik}<=10^8\)
\(0<=m<=10^5\)
\(1<=b_i<=c_i\)
Input
3
3 1 2 3
2 1 5
3 2 4 6
2
3 2 3
3 2 2
Output
2 2 3
Solution
最大值一定是每一种都挑选最后一个,次大值就是第 \(i\) 种卡片换成次大值,其中 \(i\) 满足次大值与最大值的差距最小,第三大值的情况就多起来了;
按上述思路处理出每个值之间的差,无论时间还是空间都是受不了的
但是可以搜索,利用优先队列,以和值作为关键字排序,时间上最多 \(m\) 次,空间上会出问题,例如样例 \(1\) :
\[3\qquad 2\qquad 3 \\
223 \quad 313\quad 322 \\
123\ 213\ 222\ 213\ 303\ 312\ 222\ 312\ 321
\]
从第 \(3\) 层开始,就出现了重复的,那么将这些重复的减去,空间上的问题就解决了
Code
const int N = 2e5 + 5;
int n, m, _, k;
int a[15][N];
signed main()
{
//IOS;
while(~ sd(n)){
map<vector<int>, bool> b, vis;
vector<int> res;
ll sum = 0;
rep(i, 0, n - 1){
sd(k);
res.pb(k - 1);
rep(j, 0, k - 1){
sd(a[i][j]);
}
sum += a[i][k - 1];
}
priority_queue<pair<ll, vector<int>>> q;
q.push({sum, res});
//for(auto it : res) dbg(it);
sd(m);
rep(i, 1, m){
res.clear();
rep(j, 1, n){
res.pb(read() - 1);
}
b[res] = 1;
}
vector<int> ans;
ll maxx = 0;
while(! q.empty()){
vector<int> top = q.top().second;
sum = q.top().first;
q.pop();
if(b[top]){
for(int i = 0; i < n; i ++){
if(top[i] == 0) continue;
sum -= a[i][top[i]];
top[i] --;
sum += a[i][top[i]];
if(vis[top] == 0){
q.push({sum, top});
vis[top] = 1;
}
sum -= a[i][top[i]];
top[i] ++;
sum += a[i][top[i]];
}
}
else{
maxx = sum;
ans = top;
break;
}
}
for(auto it : ans){
printf("%d ", it + 1);
}
puts("");
}
//PAUSE;
return 0;
}

浙公网安备 33010602011771号