https://daniu.luogu.org/problem/show?pid=3112
这种dp第二次遇到了,记录一下
我们看n只有20
那么n的所有状态就是只有1000000多
我们考虑对于每一个状态记录这个状态的总高度和当前最大承受力;
是不是可以通过枚举这个状态的每一个子状态得到;
比如
11
可以通过枚举
10
01
得到
那么就直接dp,用了很多位运算技巧,包括lowbit
#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const Ll N=21;
Ll a[N],b[N],c[N],f[(1<<20)],sum[(1<<20)],p[(1<<20)+5];
Ll n,m,ans=-1e18;
int main()
{
scanf("%lld%lld",&n,&m);
for(Ll i=1;i<=n;i++)scanf("%lld%lld%lld",&c[i],&b[i],&a[i]);
f[0]=1e18;
for(Ll i=1;i<=n;i++)p[(1<<(i-1))]=i;
for(Ll k=1;k<=(1<<n)-1;k++){
Ll kk=k;f[k]=-1e18;
while(kk){
Ll t=kk&-kk,v=k^t;kk-=t;t=p[t];
sum[k]+=c[t];
if(f[v]>=b[t])f[k]=max(f[k],min(f[v]-b[t],a[t]));
}
if(sum[k]>=m)ans=max(ans,f[k]);
}
if(ans==-1e18)printf("Mark is too tall");else printf("%lld",ans);
}