题解:P11427 [清华集训 2024] 绝顶之战
zhenjianuo2025 · · 题解
首先有一个基础的
注意到所有的空隙排成一个二叉树的结构。可以据此设计 DP:
下面这份代码在 QOJ 跑到了目前的最优解:
#include<bits/stdc++.h>
using namespace std;
#define vec vector
#define siz(vec) ((int)(vec).size())
#define all(vec) (vec).begin(),(vec).end()
template<class T>
void operator +=(vec<T> &a,T b){a.push_back(b);}
#define int long long
#define inf (long long)(1e18)
template<class T>
bool Min(T &x,T y){return x>y?x=y,1:0;}
template<class T>
bool Max(T &x,T y){return x<y?x=y,1:0;}
int n,m,a[16];
int f[1<<14];
int sum[1<<14],rmq[15];
int U;
int dfs(int S){
if(!S)return rmq[n];
if(f[S]!=0)return f[S];
int i=__builtin_ctz(S),SS=S^(1<<i);
for(int T=SS;;T=(T-1)&SS){
Max(f[S],dfs(T)+dfs(SS^T)+a[i]);
if(!T)break;
}
int x=rmq[i];
Min(f[S],x);
if(sum[S]>=x){
f[S]=-inf;
}
return f[S];
}
main(){
cin>>m>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
vec<int> ans;
for(int U=0;U<(1<<n);U++){
rmq[0]=m+1;
for(int i=0;i<n;i++){
rmq[i+1]=rmq[i];
if(~U>>i&1)Min(rmq[i+1],a[i]);
}
if(U)sum[U]=sum[U^(U&(-U))]+a[__builtin_ctz(U)];
memset(f,0,sizeof f);
if(dfs(U)>m){
ans+=sum[U];
}
}
sort(all(ans));
ans.erase(unique(all(ans)),ans.end());
cout<<siz(ans)<<'\n';
for(auto x:ans)cout<<x<<' ';
}