[洛谷]P1478 陶陶摘苹果(升级版) 原创
算法标签
题目简叙

思路
思路
 首先我们来理解题目的参数
1.参数n 代表一共有N个数据需要输入 2.参数a 代表我们可以达到的高度+a 3.参数b 代表我们起始高度为b 4.参数s 代表我们一共有s的被减值 5.参数x 代表每个苹果被摘掉各自需要的高度 6.参数y 代表每个苹果被摘掉各自需要的力气
现在我们理解整个逻辑:
 画一个图给大家看
 
从这张图我们可以了解到 1.a+b 等于我们可以摘取的范围 height 2.只要有苹果的高度低于 height 就是我们可以摘思路 首先我们来理解题目的参数1.参数n 代表一共有N个数据需要输入 2.参数a 代表我们可以达到的高度+a 3.参数b 代表我们起始高度为b 4.参数s 代表我们一共有s的被减值 5.参数x 代表每个苹果被摘掉各自需要的高度 6.参数y 代表每个苹果被摘掉各自需要的力气
现在我们理解整个逻辑:
 画一个图给大家看
 
从这张图我们可以了解到 1.a+b 等于我们可以摘取的范围 height 2.只要有苹果的高度低于 height 就是我们可以摘取的 3.在所有我们可以摘取的苹果中,我们要摘取最多的数量,我们肯定就要考虑当前耗费力气最小的苹果 4.一旦我们一直查找最小的苹果知道我们的力气不足以摘取任何苹果,我们就得到了最佳答案
我们依照以上的逻辑编写代码
 
现在我们依照这个逻辑来编写代码
AC代码
#include<iostream>P1478 陶陶摘苹果(升级版)
#include<algorithm>
#include<vector>
using namespace std;
#define x first
#define y second
const int N=5e3+10;
typedef pair<int,int> PII;//定义一个 PII类型 同时拥有 x y  两个数据
PII BeginArr_PII[N];//定义 PII 类型的数组 用来获取初始化数据
vector<PII>TmpArr_PII;//定义PII的不定长数组 用来进行主要的计算
int res; //答案变量
int main()
{
    int n,s,a,b;
    cin>>n>>s>>a>>b;
    int TaoHeight = a+b;//淘淘实际能获取苹果的高度
    
    for(int i=0;i<n;i++)cin>>BeginArr_PII[i].x>>BeginArr_PII[i].y;//获取初始值
    //for(int i=0;i<n;i++)cout<<BeginArr_PII[i].x<<" "<<BeginArr_PII[i].y<<endl;//给出初始值状况 x长度 y力气
    cout<<endl;
    
    for(int i=0;i<n;i++)if(BeginArr_PII[i].x<=TaoHeight)TmpArr_PII.push_back(BeginArr_PII[i]);//将所有初始数据中高度小于height的都放入不定长数组中
    
    sort(TmpArr_PII.begin(),TmpArr_PII.end(),[&](PII a,PII b){return a.y<b.y;});//所有可获得的苹果都按照耗费力气从小到大排序
    
    //for(PII i:TmpArr_PII)cout<<i.x<<" "<<i.y<<endl;//输出排序后的状况
    
    for(PII i:TmpArr_PII)if(s>=i.y)s-=i.y,res++;//只要有力气摘苹果就从小到大的耗费进行摘取,答案自增
    
    cout<<res;//返回答案
    
    return 0;
}

但这样的代码看起来稍微有些长,我们有没有办法进行优化呢?
 整理逻辑
1.初始化数据 2.把所有高度小于height的数据丢入新数组 3.对新数组排序 4.贪心累加
但细想可以发现,我们没有必要对一定高度放入,可以直接把原有数据排序,省去步骤二,只要我们自定义排序规则时添加条件即可
 更新后的AC代码
代码
#include<iostream>
#include<algorithm>
#include<vector>
    
using namespace std;
    
#define x first
#define y second
const int N=5e3+10;
typedef pair<int,int> PII;
vector<PII>TmpArr_PII;
int res;
    
int main()
{
    int n,s,a,b;
    cin>>n>>s>>a>>b;
    int TaoHeight = a+b;
    for(int i=0;i<n;i++){int x,y;cin>>x>>y;TmpArr_PII.push_back({x,y});}
    
    sort(TmpArr_PII.begin(),TmpArr_PII.end(),[&](PII a,PII b){return a.y<b.y;});
        
    for(PII i:TmpArr_PII)if(s>=i.y&&i.x<=TaoHeight)s-=i.y,res++;
        
    cout<<res;
        
    return 0;
}

 我们成功压缩了一半的代码量 并且快了4MS
然后是,抄作业的同志,这个做法我写完之后去题解看了一圈都没有这么做的
 所以抄的时候不要直接抄这个,因为没人这么写
 除了我
方法2
 现在我们来考虑更容易理解的方法
我们采用桶排序的方式来规避多一个点 同时具有 力气 高度 两个参数的情况
#include<iostream>
using namespace std;
int n,s,a,b;
const int N=100+10;
const int y_len=100;
int arr[N];
int main()
{
    cin>>n>>s>>a>>b;
    const int height=a+b;//小红能达到的长度
    
    for(int i=0;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        
        if(x<=height)arr[y]++;//以y作为下标 如果这个苹果的高度小于可以达到的 我们就表示 目标力气的苹果+1
    }
    
    
    int res=0;
    for(int i=0;i<=y_len;i++)
        if(s>=i)
            while(arr[i]--)
                if(s>=i)s-=i,res++;//这里的while持续自减是为了避免 我们一次减少多个数字把自己更新为了负数的情况
        else break;//
        
    cout<<res;
    
    return 0;
}
```取的
	3.在所有我们可以摘取的苹果中,我们要摘取最多的数量,我们肯定就要考虑当前耗费力气最小的苹果
	4.一旦我们一直查找最小的苹果知道我们的力气不足以摘取任何苹果,我们就得到了最佳答案
</pre>
我们依照以上的逻辑编写代码

现在我们依照这个逻辑来编写代码
AC代码
```cpp
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define x first
#define y second
const int N=5e3+10;
typedef pair<int,int> PII;//定义一个 PII类型 同时拥有 x y  两个数据
PII BeginArr_PII[N];//定义 PII 类型的数组 用来获取初始化数据
vector<PII>TmpArr_PII;//定义PII的不定长数组 用来进行主要的计算
int res; //答案变量
int main()
{
    int n,s,a,b;
    cin>>n>>s>>a>>b;
    int TaoHeight = a+b;//淘淘实际能获取苹果的高度
    
    for(int i=0;i<n;i++)cin>>BeginArr_PII[i].x>>BeginArr_PII[i].y;//获取初始值
    //for(int i=0;i<n;i++)cout<<BeginArr_PII[i].x<<" "<<BeginArr_PII[i].y<<endl;//给出初始值状况 x长度 y力气
    cout<<endl;
    
    for(int i=0;i<n;i++)if(BeginArr_PII[i].x<=TaoHeight)TmpArr_PII.push_back(BeginArr_PII[i]);//将所有初始数据中高度小于height的都放入不定长数组中
    
    sort(TmpArr_PII.begin(),TmpArr_PII.end(),[&](PII a,PII b){return a.y<b.y;});//所有可获得的苹果都按照耗费力气从小到大排序
    
    //for(PII i:TmpArr_PII)cout<<i.x<<" "<<i.y<<endl;//输出排序后的状况
    
    for(PII i:TmpArr_PII)if(s>=i.y)s-=i.y,res++;//只要有力气摘苹果就从小到大的耗费进行摘取,答案自增
    
    cout<<res;//返回答案
    
    return 0;
}

但这样的代码看起来稍微有些长,我们有没有办法进行优化呢?
 整理逻辑
1.初始化数据 2.把所有高度小于height的数据丢入新数组 3.对新数组排序 4.贪心累加
但细想可以发现,我们没有必要对一定高度放入,可以直接把原有数据排序,省去步骤二,只要我们自定义排序规则时添加条件即可
 更新后的AC代码
#include<iostream>
#include<algorithm>
#include<vector>
    
using namespace std;
    
#define x first
#define y second
const int N=5e3+10;
typedef pair<int,int> PII;
vector<PII>TmpArr_PII;
int res;
    
int main()
{
    int n,s,a,b;
    cin>>n>>s>>a>>b;
    int TaoHeight = a+b;
    for(int i=0;i<n;i++){int x,y;cin>>x>>y;TmpArr_PII.push_back({x,y});}
    
    sort(TmpArr_PII.begin(),TmpArr_PII.end(),[&](PII a,PII b){return a.y<b.y;});
        
    for(PII i:TmpArr_PII)if(s>=i.y&&i.x<=TaoHeight)s-=i.y,res++;
        
    cout<<res;
        
    return 0;
}

 我们成功压缩了一半的代码量 并且快了4MS
然后是,抄作业的同志,这个做法我写完之后去题解看了一圈都没有这么做的
 所以抄的时候不要直接抄这个,因为没人这么写
 除了我
代码
方法2
 现在我们来考虑更容易理解的方法
我们采用桶排序的方式来规避多一个点 同时具有 力气 高度 两个参数的情况
#include<iostream>
using namespace std;
int n,s,a,b;
const int N=100+10;
const int y_len=100;
int arr[N];
int main()
{
    cin>>n>>s>>a>>b;
    const int height=a+b;//小红能达到的长度
    
    for(int i=0;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        
        if(x<=height)arr[y]++;//以y作为下标 如果这个苹果的高度小于可以达到的 我们就表示 目标力气的苹果+1
    }
    
    
    int res=0;
    for(int i=0;i<=y_len;i++)
        if(s>=i)
            while(arr[i]--)
                if(s>=i)s-=i,res++;//这里的while持续自减是为了避免 我们一次减少多个数字把自己更新为了负数的情况
        else break;//
        
    cout<<res;
    
    return 0;
}
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号