PAT(甲级)2020年秋季考试

7-1 Panda and PP Milk (20分)

在这里插入图片描述
题意: n 只熊猫排成一排喝奶。每只熊猫至少分配 200ml 的牛奶,如果一个熊猫比它旁边的熊猫重,那么就需要比旁边的熊猫至少多喝 100ml 的牛奶。如果体重相同,分配的牛奶要相同。问最少需要分配多少的牛奶,才能满足要求

思路:从左往右扫一遍,每只熊猫都和左边的比。然后从右往左扫一遍,每只熊猫都和右边的比。这样就可以满足条件了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n;
int a[maxn],val[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
    int cur=10000;
    for(int i=1; i<=n; ++i)
    {
        if(a[i]>cur) val[i]=val[i-1]+100;
        else if(a[i]==cur) val[i]=val[i-1];
        else val[i]=200;
        cur=a[i];
    }
    cur=10000;
    for(int i=n; i>=1; --i)
    {
        if(a[i]>cur)
        {
            val[i]=max(val[i+1]+100,val[i]);
        }
        else if(a[i]==cur)
        {
            val[i]=max(val[i],val[i+1]);
        }
        else val[i]=max(val[i],200);
        cur=a[i];
    }
    int ans=0;
    for(int i=1; i<=n; ++i) ans+=val[i];
    printf("%d\n",ans);
    return 0;
}

7-2 How Many Ways to Buy a Piece of Land (25分)

在这里插入图片描述
题目链接

题意:给定 n 块地,m 块钱,每块地的价格为 a i a_i ai 。你可以选择一个区间 [ l , r ] [l,r] [l,r] 买地,问有几种不同的买法?

思路:二分。枚举起点 i,对每一个 i 找到最右边可以买的地方。中间的都是可以选择的。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n,m;
int a[maxn],pref[maxn];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; ++i) scanf("%d",&a[i]),pref[i]=pref[i-1]+a[i];
    int ans=0;
    for(int i=1; i<=n; ++i)
    {
        int L=i,R=n;
        while(L<R)
        {
            int mid=(L+R+1)>>1;
            if(pref[mid]-pref[i-1]<=m) L=mid;
            else R=mid-1;
        }
        if(pref[L]-pref[i-1]<=m) ans+=L-i+1;
    }
    printf("%d\n",ans);
    return 0;
}

7-3 Left-View of Binary Tree (25分)

在这里插入图片描述

题意:给定中序和前序遍历的结果,求一颗二叉树的左视图

思路:常规建树操作。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n;
int a[maxn],b[maxn];
struct Node
{
    int val,depth;
    Node* ls,* rs;
};
Node* build(int l1,int r1,int l2,int r2,int depth)
{
    if(l1>r1) return NULL;
    int pos;
    for(pos=l1; pos<=r1; ++pos)
        if(a[pos]==b[l2]) break;
    int len1=pos-l1;
    int len2=r1-pos;
    Node* node=new Node;
    node->val=b[l2];
    node->depth=depth;
    node->ls=build(l1,pos-1,l2+1,l2+len1,depth+1);
    node->rs=build(pos+1,r1,l2+len1+1,r2,depth+1);
    return node;
}
int visit[maxn];
vector<int> ans;

void bfs(Node* root)
{
    queue<Node*> q;
    q.push(root);
    while(!q.empty())
    {
        Node* t=q.front();
        q.pop();
        if(!visit[t->depth])
        {
            visit[t->depth]=1;
            ans.push_back(t->val);
        }
        if(t->ls!=NULL) q.push(t->ls);
        if(t->rs!=NULL) q.push(t->rs);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
    for(int i=1; i<=n; ++i) scanf("%d",&b[i]);
    Node* root=build(1,n,1,n,1);
    bfs(root);
    int m=ans.size();
    for(int i=1; i<=m; ++i) printf("%d%c",ans[i-1],i==m?'\n':' ');
    return 0;
}

7-4 Professional Ability Test (30分)

在这里插入图片描述
题意:有 n 个等级,等级之间存在前置关系。假设 A 等级是 B 等级的前置,A 需要达到 S 分,才能达到 B 等级,并且会获得 D 元的代金券。现有 m 个关系,k 个询问,问 T 点能否直接到达,或者求最短(分数最少)的达到 T 的路径。如果最短路相同,则输出获得代金券最多的路径。

思路

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1010,inf=1e9;

int n,m;
struct Egde
{
    int v,w,val;
};
vector<Egde> e[maxn];
int in[maxn],dis[maxn],val[maxn],pre[maxn];
int op[maxn],out[maxn];

void topo()
{
    for(int i=0; i<=n-1; ++i)
    {
        dis[i]=inf;
        val[i]=0;
        pre[i]=-1;
    }
    queue<int> q;
    for(int i=0; i<=n-1; ++i)
    {
        if(in[i]==0)
        {
            q.push(i);
            dis[i]=0;
            val[i]=0;
        }
    }
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(auto x: e[u])
        {
            int v=x.v,w=x.w;
            in[v]--;
            if(in[v]==0) q.push(v);
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                val[v]=val[u]+x.val;
                pre[v]=u;
            }
            else if(dis[v]==dis[u]+w)
            {
                if(val[v]<val[u]+x.val)
                {
                    val[v]=val[u]+x.val;
                    pre[v]=u;
                }
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1; i<=m; ++i)
    {
        int u,v,s,d;
        cin>>u>>v>>s>>d;
        e[u].push_back({v,s,d});
        in[v]++;
        out[v]++;
    }
    topo();
    int k;
    scanf("%d",&k);
    for(int i=1; i<=k; ++i) scanf("%d",&op[i]);
    bool ok=1;
    for(int i=1; i<=k; ++i)
        if(dis[op[i]]==inf) ok=0;
    if(ok)
    {
        puts("Okay.");
        for(int i=1; i<=k; ++i)
        {
            vector<int> ans;
            for(int p=op[i]; p!=-1; p=pre[p]) ans.push_back(p);
            reverse(ans.begin(),ans.end());
            int m=ans.size();
            if(m==1) printf("You may take test %d directly.\n",op[i]);
            else for(int i=1; i<=m; ++i) printf("%d%s",ans[i-1],i==m?"\n":"->");
        }
    }
    else
    {
        puts("Impossible.");
        for(int i=1; i<=k; ++i)
        {
            if(out[op[i]]!=0) puts("Error.");
            else printf("You may take test %d directly.\n",op[i]);
        }
    }
    return 0;
}

总结

7-1:左右扫一遍即可。一开始想的是以大小来贪心,会有点错误。。
7-2:二分结束之后,需要check一下,这个二分的结果 L 是否符合要求。
7-3:无
7-4:无

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值