先放个题目链接:https://codeforces.com/contest/1574/problem/D
当时没做出来,想了一阵子百思不得其解。今天A掉了说一说我的思路
先来说一下题目大意,大体就是你在打游戏,有n种装备需要选择(n<=10),每一种装备都有c个可供选择(c<=2e5),按照战力值升序给出。但是也同时存在着m(m<=2e5)种装备组合方案被ban掉了,现在让你列出没被ban掉的装备组合中能达到最大战力和的装备组合是什么样的。
解题思路:
先去想最暴力的做法,设置n个指针分别指向每一种装备最大战力值的装备,然后dfs选择哪个装备退化(指针左移),如果当前所搜索到的装备组合没有被ban掉,那么更新答案,因为这时任何一个指针左移都会使新的组合方案弱于当前战力值,所以一旦dfs搜索到了一种没被ban掉的方案了就要停止搜索了。所以说最后所有供更新答案用的组合方案都是通过被ban掉的方案演化而来。
这正解不就来了吗,我们可以枚举每一种被ban的方案,然后再枚举选择哪一个指针左移,记录哪一种方案使得战力值之和最大。
#include <bits/stdc++.h>
using namespace std;
int item[20][250005],ansum,ans[20];
int banned[250005][20];
int main(){
map<vector<int>,bool>c;
int n,m;
cin>>n;
for(int i=1;i<=n;i++){
cin>>item[i][0];
for(int j=1;j<=item[i][0];j++){
cin>>item[i][j];
}
}
cin>>m;
for(int i=1;i<=m;i++){
vector<int>v(n);
for(int j=0;j<n;j++) {
cin>>v[j];
banned[i][j+1]=v[j];
}
c[v]=1;
}
int sum=0;
vector<int>v(n);
for(int i=1;i<=n;i++){
sum+=item[i][item[i][0]];
v[i-1]=item[i][0];
}
if(!c[v]){
for(int i=0;i<v.size();i++){
cout<<v[i]<<" ";
}
return 0;
}
for(int i=1;i<=m;i++){
sum=0;
for(int j=1;j<=n;j++){
sum+=item[j][banned[i][j]];
}
for(int j=1;j<=n;j++){
if(banned[i][j]==1) continue;
vector<int>ttmp(n);
for(int k=0;k<n;k++) ttmp[k]=banned[i][k+1];
ttmp[j-1]--;
int tmp=sum-(item[j][banned[i][j]]-item[j][banned[i][j]-1]);
if(tmp>ansum&&!c[ttmp]){
ansum=tmp;
for(int k=1;k<=n;k++) ans[k]=banned[i][k];
ans[j]--;
}
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}
Comments | NOTHING