正题
题目链接:https://www.luogu.org/problemnew/show/P3112
题目大意
有nnn只牛,每只牛有hi,wi,sih_i,w_i,s_ihi,wi,si分别表示有多高,有多重,上面最多承载总共多重的牛。
选择一些牛依次摆放要求高度超过TTT且上面还能增加最重的物品。
解题思路
首先我们考虑已经选定了牛了,然后如何摆放是最优的:
resti=si−∑j=i+1nwjrest_i=s_i-\sum_{j=i+1}^nw_jresti=si−j=i+1∑nwj
我们考虑是否交换两项
resti=si−(∑j=i+1nwj)rest_i=s_i-(\sum_{j=i+1}^nw_j)resti=si−(j=i+1∑nwj)
resti+1=si+1−(∑j=i+1nwj)−wirest_{i+1}=s_{i+1}-(\sum_{j=i+1}^nw_j)-w_iresti+1=si+1−(j=i+1∑nwj)−wi
考虑是否交换要求
max{min{resti,resti+1},min{Nresti,Nresti+1}}max\{min\{rest_i,rest_{i+1}\},min\{Nrest_i,Nrest_{i+1}\}\}max{min{resti,resti+1},min{Nresti,Nresti+1}}
两边同时加上(∑j=i+1nwj)(\sum_{j=i+1}^nw_j)(∑j=i+1nwj)
那么就是求
max{min{si,si+1−wi},min{si+1,si−wi+1}}max\{min\{s_i,s_{i+1}-w_i\},min\{s_{i+1},s_{i}-w_{i+1}\}\}max{min{si,si+1−wi},min{si+1,si−wi+1}}
然后si>si−+wi−1s_i>s_{i}-+w_{i-1}si>si−+wi−1且si+1>si+1−wis_{i+1}>s_{i+1}-w_isi+1>si+1−wi(显而易见)
如果si+1−wi≤si−wi−1s_{i+1}-w_i\leq s_i-w_{i-1}si+1−wi≤si−wi−1
那么有si+1−wi≤sis_{i+1}-w_i\leq s_isi+1−wi≤si那么交换肯定更优
那么只要si+wis_i+w_isi+wi从大到小选择就好了。
codecodecode
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const ll N=21;
ll n,T,sh,maxs,ans,w,MS;
struct node{ll h,w,s;
}a[N];
bool cmp(node x,node y)
{return x.s+x.w>y.s+y.w;}
int main()
{scanf("%lld%lld",&n,&T);for(ll i=1;i<=n;i++)scanf("%lld%lld%lld",&a[i].h,&a[i].w,&a[i].s);sort(a+1,a+1+n,cmp);MS=1<<n;ans=-1;for(ll i=0;i<MS;i++){sh=w=0;maxs=2147483647;for(ll j=n;j>=1;j--)if((i>>j-1)&1){sh+=a[j].h;maxs=min(maxs,a[j].s-w);w+=a[j].w;}if(sh<T) continue;ans=max( maxs,ans);}if(ans<0)printf("Mark is too tall");else printf("%lld",ans);
}