4.3递归&4.4贪心

目录

4.3递归

4.4贪心

PAT A1070 Mooncake (25 分)

PAT A1033 To Fill or Not to Fill (25 分)

PAT A1033 To Fill or Not to Fill (25 分)

PAT A1067 Sort with Swap(0, i) (25 分)

PAT A1038 Recover the Smallest Number (30 分)


4.3递归

递归没有相应的练习挖个坑在这里,递归在树那边比较常用。

4.4贪心

思想就是取当前状态下的局部最优的策略。数学建模用过,主要能证明局部最优就是全局最优就可以使用这个方法。

PAT A1070 Mooncake (25 分)

#include<cstdio>
#include<algorithm>
using namespace std;
struct mooncake{
    double store;       //表示这种月饼的库存量
    double sell;        //表示这种月饼的总售价
    double price;       //表示这种月饼的单价
}cake[1010];
bool cmp(mooncake a,mooncake b)
{
    return a.price>b.price;
}
int main()
{
    int N,D;
    scanf("%d %d",&N,&D);       //N是月饼的种类,D是表示市场的最大需求
    int i=0;
    for(i=0;i<N;i++)
    {
        scanf("%lf",&cake[i].store);        //读入库存量
    }
    for(i=0;i<N;i++)
    {
        scanf("%lf",&cake[i].sell);         //读入总售价
        cake[i].price=cake[i].sell/cake[i].store;       //求出平均价格
    }
    sort(cake,cake+N,cmp);      //从大到小进行排序
    double profit=0;
    for(i=0;i<N;i++)
    {
        if(cake[i].store<=D){
            D-=cake[i].store;
            profit+=cake[i].sell;
        }
        else{
            profit+=D*cake[i].price;
            break;
        }
    }
    printf("%.2f\n",profit);
    return 0;
}

这题目主要是比较单价月饼的大小进行排序,排序后进行输出。

扫描二维码关注公众号,回复: 8780057 查看本文章

PAT A1033 To Fill or Not to Fill (25 分)

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=510;
const int INF=100000000;

struct station{
    double Pi;     //the unit gas price
    double Di;     //the distance between the station and Hangzhou
}st[maxn];

bool cmp(station a,station b)       //按距离从小到大进行排序
{
    return a.Di<b.Di;
}

int main()
{  
    double Cmax,D,Davg;
    int N;
    scanf("%lf %lf %lf %d",&Cmax,&D,&Davg,&N);      
    //读取邮箱的最大容量,杭州到目的城市的距离,消耗单位的油能跑的距离,加油站的数量
    for(int i=0;i<N;i++)
    {
        scanf("%lf %lf",&st[i].Pi,&st[i].Di);
    }
    st[N].Pi=0;     //设置终点的价格为0
    st[N].Di=D;     //设置终点距离为D
    sort(st,st+N,cmp);      //排序
    if(st[0].Di!=0){        //如果排序的第一个加油站的距离不是0,说明无法前进
        printf("The maximum travel distance = 0.00\n");
    }else{
        int now=0;          //当前所处的加油站编号
        double ans=0,nowtank=0,Max=Cmax*Davg;       //总花费、当前油量以及满油行驶距离
        while(now<N){       //从每次循环将选出第一个油价低于当前油价的加油站
            //如果没有低于当前价格的,则选出价格最低的那个
            int k=-1;                   //最低油价的编号
            double priceMin=INF;        //最低油价
            for(int i=now+1;i<=N&&st[i].Di-st[now].Di<=Max;i++){
                if(st[i].Pi<priceMin){      //如果比当前最低油价要低
                    priceMin=st[i].Pi;      //更新最低油价
                    k=i;
                    if(priceMin<st[now].Pi)
                    {
                        break;
                    }
                }
            }
            if(k==-1)break;     //满油状态下找不到加油站,退出循环输出结果
            //下面为能找到可到达的加油站k,计算转移花费
            //need 为从now到k需要的油量
            double need=(st[k].Di-st[now].Di)/Davg;
            if(priceMin<st[now].Pi){    //如果加油站当前的油价高于加油站k的油价
                //只需要买到到达k加油站的油
                if(nowtank<need){       //如果当前油量不足need
                    ans+=(need-nowtank)*st[now].Pi;     //补足need
                    nowtank=0;          //到达加油站k后邮箱的油量为0
                }else{      //如果当前油量超过need
                    nowtank-=need;      //直接到达加油站k
                }
            }else{     //如果加油站k的油价高于当前油价,则需要加满
                ans+=(Cmax-nowtank)*st[now].Pi;     //将油箱加满
                nowtank=Cmax-need;
            }
            now=k;      //到达加油站k,进入下一层循环
        }
        if(now==N){     //能到达终点
            printf("%.2f\n",ans);
        }else{          //不能到达终点
            printf("The maximum travel distance = %.2f\n",st[now].Di+Max);
        }
    }
    return 0;
}

这道题目很难,主要需要考虑清楚每一步的策略,一步步的分析清楚情况。

1、判断起点是否有加油站,没有距离则为0;

2、在当前加油站now,寻找下一个加油站。

      a.寻找比当前加油站最近的且油价低于now的加油站,加到能够到达加油站的油(油分两种,用现在的油就可以到达不用再加就是油够的情况,第二种是油不够,需要加到油刚好够)。

      b.如果找不到a加油站,就找油价相比较而言最低的加油站,当前需要加满油。

      c.满油都找不到,输出最远距离结束。

PAT A1033 To Fill or Not to Fill (25 分)

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010;
int coupon[maxn],product[maxn];
int main()
{
    int n,m;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&coupon[i]);
    }
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d",&product[i]);
    }
    sort(coupon,coupon+n);      //从小到大
    sort(product,product+m);        //从小到大排序
    int i=0,j,ans=0;
    while(i<n&&i<m&&coupon[i]<0&&product[i]<0)
    {
        ans+=coupon[i]*product[i];      //当前位置小于0,累加乘积
        i++;
    }
    i=n-1;
    j=m-1;
    while(i>=0&&j>=0&&coupon[i]>0&&product[j]>0)
    {
        ans+=coupon[i]*product[j];      //当前位置均大于0,累加乘积
        i--,j--;
    }
    printf("%d",ans);
    return 0;
}

从小到大排序后,分负数与正数分比别进行计算,注意就i与j的取值。

PAT A1067 Sort with Swap(0, i) (25 分)

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=100010;
int pos[maxn];      //存放各数字当前所处的位置编号
int main()
{
    int n,ans=0;        //ans表示总交换次数
    scanf("%d",&n);
    int left=n-1,num;       //left存放除0以外不在本位上的数的个数
    for(int i=0;i<n;i++){
        scanf("%d",&num);
        pos[num]=i;     //num所处的位置为i
        if(num==i&&num!=0){     //如果除0以外有在本位上的数
            left--;     //令left减1
        }
    }
    int k=1;        //k存放除0以外当前不在本位上的最小数
    while(left>0){      //只要还有数不在本位上
        //如果0在本位上,则寻找一个当前不在本位上的数与0交换
        if(pos[0]==0)
        {
            while(k<n)
            {
                if(pos[k]!=k){      //找到一个当前不在本位上的数k
                    swap(pos[0],pos[k]);        //将k与0交换位置
                    ans++;      //交换次数加1
                    break;
                }
                k++;        //判断k+1是否在本位上
            }
        }
        //只要0不在本位上,就将0所在位置的数的当前所在位置与0的位置交换
        while(pos[0]!=0)
        {
            swap(pos[0],pos[pos[0]]);       //将0与pos[0]交换
            ans++;      //交换次数加1
            left--;     //不在本为上的数的个数减1
        }
    }
    printf("%d\n",ans);     //输出结果
    return 0;
}

注意0要考虑是不是在本位上,如果在需要找一个不在本为上的数进行交换。

PAT A1038 Recover the Smallest Number (30 分)

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>

using namespace std;
const int maxn=10010;
string str[maxn];

bool cmp(string a ,string b)
{
    return a+b<b+a;     //核心算法,a+b组合与b+a组合进行对比,大的放在前面
}

int main()
{
    int n;
    cin >>n;
    for (int i=0;i<n;i++)
    {
        cin>>str[i];
    }
    sort(str,str+n,cmp);        //排序
    string ans;         //结果字符串
    for(int i=0;i<n;i++)
    {
        ans+=str[i];        //将排序后的数字串进行拼接
    }
    while(ans.size()!=0&&ans[0]=='0')
    {
        ans.erase(ans.begin());     //去除前导0
    }
    if(ans.size()==0)cout <<0;      //去除前导0后为空,输出0
    else cout<<ans;         //否则输出结果
    return 0;
}

string的使用,不太熟练,要好好看看。

发布了24 篇原创文章 · 获赞 6 · 访问量 470

猜你喜欢

转载自blog.csdn.net/qq_39965800/article/details/98104976
4.3
4.4