分析

看到数据范围就直接想状压。对于每一种状态,它的高度是一定的,你更改上下次序只会影响上面还能放多少重量,所以用 \(H[i]\) 预处理 \(i\) 这个状态总高度多少,用 \(f[i]\) 表示 \(i\) 这个状态最多上面还能放多少重量,转移应是新放的牛的承重量和被转移的 \(f\) 值减去该牛重量,最后找答案时,取最大的满足 \(H[i]\) 大于等于所需高度的 \(i\)\(f[i]\) 就行了。

代码

#include <bits/stdc++.h>
using namespace std;
inline void read(int &res){
	res=0;
	int f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')res=(res<<1)+(res<<3)+c-48,c=getchar();
	res*=f;
}
int n,m;
int N;
int h[25],w[25],s[25];
int f[1100005];
int H[1100005];
int zy[25];
signed main()
{
	read(n);read(m);
	N=(1<<n)-1;
	for(int i=1;i<=n;i++){
		zy[i]=(1<<(i-1));
		read(h[i]);read(w[i]);read(s[i]);
	}
	for(int i=0;i<=N;i++){
		f[i]=-1e9;
		for(int j=1;j<=n;j++){
			if(i&zy[j])H[i]+=h[j];//预处理状态高度和 
		}
	}
	for(int i=1;i<=n;i++){
		f[zy[i]]=s[i];//预处理,先放一头 
	}
	for(int i=1;i<=N;i++){
		for(int j=1;j<=n;j++){
			if(!(i&zy[j])){
				f[i|zy[j]]=max(f[i|zy[j]],min(f[i]-w[j],s[j]));
			}
		}
	}
	int ans=-1;
	for(int i=1;i<=N;i++){
		if(H[i]>=m&&f[i]>=0){
			ans=max(ans,f[i]);
		}
	}
	if(ans<0)puts("Mark is too tall");
	else cout<<ans;
	return 0;
}

posted on 2021-11-19 11:31  漠寒·  阅读(6)  评论(0编辑  收藏  举报