目录
一、前言
因为昨天有聊到如何使用c++里面的sort函数,并且着重介绍了sort与结构体的结合解决一些贪心的算法题目,那不就来了嘛,为了让一些读者有更好的连续性,所以今天这一题就是介绍结构体和sort的联合使用的妙处,这题是一个部分背包问题,那么相信很多熟悉DP问题的读者,肯定会想到背包问题肯定就是一个dp动态规划嘛,要找一些dp数组,但是此题如果利用动态规划去做的话,会有很多的问题甚至是做不出来的,大家可以体会一下!!前文的链接(sort函数讲解)
二、题目描述
三、题目解读
其实题目大家都看得懂,所以主要想介绍一下,这里的贪心思想。我们可以看到藏宝洞里面的N堆藏金币,然后每一堆的金币有相应的价格,然而题目说到了所有的金币都是可以随意分割的,这个大家必须好好理解,也就是说,假设你背包只剩下5kg的重量可以装了,都是剩余的金币,每一堆金币的重量都大于5kg,如果按照背包的基本动态规划来想的话,是没有办法继续加上任何一堆金币的价格的,但是本题不同点就在,我可以只拿其中金币的一堆的5kg然后得到它对应的价格哦!那么这个时候的贪心思想是什么呢?我们一定会拿1单位价格/kg最高的那一堆金币,也就是v/m(m表示总质量,v表示总价格)最大的那一堆,那么按照这一个思想,从一开始,就让所有堆的金币按照v/m从大到小排序,然后依次进行贪心的拿取,那么到最后一定能得到最大的钱!!当然,这样,聪明的你就可以发家致富了哈哈哈哈!
四、完整代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
int m; //每一堆的总质量
int v; //每一堆的总价格
};
node a[105];
bool com(node aa,node bb)
{
return aa.v*bb.m>aa.m*bb.v; //这个写法避免浮点数精度的影响,就是移项
}
int main()
{
double ans=0;
int N,T;
cin>>N>>T;
for(int i=1;i<=N;i++)
{
cin>>a[i].m>>a[i].v;
}
sort(a+1,a+N+1,com); //因为下标是从1开始,所以sort的前后都加一个1就好了
for(int i=1;i<=N;i++)
{
if(T>=a[i].m) //能够拿全,就全部拿下
{
ans+=a[i].v;
T-=a[i].m;
}
else
{
ans=ans+T*(double(a[i].v)/double(a[i].m)); //如果拿不全就能拿多少拿多少
break;
}
}
printf("%.2lf",ans); //按照题目要求进行输出
}
五、细节解读
①com函数里面的写法:其实想表示v1/m1>v2/m2,但是按照本蒟蒻的代码来看,移项之后再进行一个比较,其实是能够避免一些因为精度问题比较上的失误,这个写法以后大家在遇到类似的题目也会有相应的经验的!
②if-else:主函数的这一处判断正是和背包问题的不同地方,遵循能拿就拿的原则,且拿的顺序已经被固定,相当于每一次的判断拿取,都是在拿一个最优解。贪心的思想就是每一个子问题都拿到了最优解,那么最终的答案也一定会是最优解!
六、AC凭证
七、水话
从上面的题目我们可以看出,结构体结合sort是有多么的便捷,而且大家在判断一个题目是什么算法的时候,一个不能仅仅因为题目来判定,一定要仔细的读题,然后找到这个题目隐藏的条件,好好判断该利用什么思路解题。比如这题如果刚开始就去想动态规划,一定会浪费很多的时间去纠正这一个错误的思想的!啊啊啊啊每日一水题解写完了,下午要考线代,祝我加油鸭!