赛后补完这道题可以说有两个收获,一个就是关于贪心算法的正确性的证明,和结构体的实际应用
先从简单说起,因为学完结构体之后一直没有什么机会使用,所以对结构体的知识也挺生疏的,但这道题需要用结构体把编号和价值联系起来,需要注意的是结构体内的变量种类也可变,使用时在定义后加.即可
然后讲讲这道题的贪心策略,这个题的状态是空的,你要预判那这个物品会带来的影响,你会多获得价值a并且你的对手少了获得价值b的机会,一来一回就是差了a+b,但很多人看问题直接会绝对不应该这样限制,或者就算知道该这么贪也不知为什么,我用两种不同的方法试着说明这个问题
一,我们先假设所有货物已经选完了,如果牛牛放弃一个牛可乐也放弃一个牛牛的价值会-a1,牛可乐的价值会+b1,a1+b1的和即为差值,也就是如果牛牛不选这个会造成的差值,所以我们可以得出结论,先拿a[I]+b[I]的和更大的结果
第二种就是用不等式计算作者:Ycrpro
链接:https://ac.nowcoder.com/discuss/364961?type=101&order=0&pos=2&page=2
来源:牛客网
如果 牛牛的 (a1,b1) 物品与 牛可乐的(a2,b2) 交换,则 N′=N−a1+a2,M′=M+b1−b2 对于 牛牛(目标是最大化 N−M)来说会变得更优仅当 a1+b1>a2+b2满足( N′−M′>N−M 化简就能得到),对于 牛可乐也一样。所以两人都会优先选择 ai+bi最大的物品。
下面是ac程序
#include<bits/stdc++.h>
using namespace std;
struct qqq
{
int a,b,id;
};
bool cmp(qqq x,qqq y)
{
return x.a+x.b>y.a+y.b;
}
int main()
{
int n;
cin>>n;
qqq f[n+5];
for(int i=1;i<=n;i++)
{
cin>>f[i].a;
f[i].id=i;
}
for(int i=1;i<=n;i++)
cin>>f[i].b;
sort(f+1,f+1+n,cmp);
for(int i=1;i<=n;i+=2)
printf("%d ",f[i].id);
printf("\n");
for(int i=2;i<=n;i+=2)
printf("%d ",f[i].id);
printf("\n");
return 0;
}