看到没有完整的贪心题解,本蒟蒻决定来补充一发(没有完整证明的贪心是不圆满的)
不知道大家做过NOIP2012国王游戏没,这两道题思路相似
进入正题,看着就像贪心的一道题
怎么贪,按height,strength,weight排序好像都不合适
试图分析相邻两项交换的影响
一个位置的承重量可以这样表示Resti=Strengthi-∑Weightj(j>i)
同理,它的下一项可以如下表示Resti+1=Strengthi+1-∑Weightj(j>i+1)
相邻两项交换后是这样的
Resti=Strengthi+1-Weighti-∑Weigthj(j>i+1)
Resti+1=Strengthi-∑Weightj(j>i+1)
我们要使稳定强度最大,即最大化Min(Resti)
还是考虑这相邻两项,我们考虑是否交换就转化为了判断这个东西
max(min(PreResti,PreResti+1),min(NextResti,NextResti+1))
为了简化式子
我们给上述每项同加∑Weightj(j>i+1)
上式化简为
max((Pre)min(Strengthi-Weighti+1,Strengthi+1}),(Next)min(Strengthi+1-Weighti,Strengthj))
观察到
Strengthi>=Strengthi-Weighti+1,Strengthi+1>Strengthi+1-Weighti
如果
Strengthi+1-Weighti<=Strengthi-Weighti+1<=Strengthi
那么Next中min的一定是Strengthi+1-Weighti,而Pre中每一项都大于它,即交换前总优于交换后
反之,交换后优于交换前
移项得,
Strengthi+Weighti>=Strengthi+1+Weighti+1
时,交换前更优
所以我们按照Strength+Weight从大到小排序即可
然后2^n枚举选择哪些牛,对于每种情况,求出Rest的最小值,然后在其中取最大即可
上代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
int h,w,s;
}a[30];
int n,h;
bool c[30];
long long ans=-1;
bool cmp(const node &x,const node &y)
{
return x.w+x.s>y.w+y.s;
}
void dfs(int x,int ch)
{
c[x]=ch;
if(x==n)
{
long long tmp=1e9,len=0;
for(int i=1;i<=n;i++)
if(c[i])
{
len+=a[i].h;
long long sum=0;
for(int j=i+1;j<=n;j++)
sum+=c[j]?a[j].w:0;
tmp=min(tmp,a[i].s-sum);
}
if(len>=h)
ans=max(ans,tmp);
return;
}
dfs(x+1,1);
dfs(x+1,0);
}
int main()
{
scanf("%d%d",&n,&h);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&a[i].h,&a[i].w,&a[i].s);
sort(a+1,a+n+1,cmp);
dfs(0,0);
if(ans==-1)
printf("Mark is too tall
");
else
printf("%lld
",ans);
return 0;
}