PAT-2022年春季考试-甲级,题解

仅提供个人思路~

题目链接:购买考试券 - PAT(甲级)2022年春仿真卷 (pintia.cn)

7-1 Simple Lie Detection (20 分)

/*
    n道题,阈值为t(分数超过t要输出!!!) ,k个作答
    判题规则: 
    1.字符串首字母为f,分数-2
    2.字符串尾字母为a,分数-1
    3.每个相同相同字母的len>5的最长答案段,分数+3
        即aaaaaaabbbbbbccccccc,分数为9
    4.字母a后为e或者h,分数-4
    5.连续递增字母且len>3,分数+5 
*/

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,t,k;
    cin>>n>>t>>k;
    while(k--)
    {
        int res=0;
        string s;
        cin>>s;
        if(s[0]=='f')res-=2;
        if(s[n-1]=='a')res-=1;
        
        //for every longest segment of answeres where the same letter is chosen for consecutive questions, 
        //if the segment length is larger than 5, the score is to +3;
        //记录每个字母的最长连续段 
        int longest_len[200]={0};
        for(int i=0;i<n;)
        {
            int tmp_len=0;
            if(i+5<n&&s[i]==s[i+1]&&s[i]==s[i+2]&&s[i]==s[i+3]&&s[i]==s[i+4]&&s[i]==s[i+5])
            {
                i+=5;
                tmp_len+=5;
                while(s[i]==s[i+1]&&i+1<n)i++,tmp_len++;
            }
            else i++;
            if(tmp_len>longest_len[s[i-1]])longest_len[s[i-1]]=tmp_len;
        }
        //验证字母的连续段是否与longest_len相符,是则+5 
        for(int i=0;i<n;)
        {
            int tmp_len=0;
            if(i+5<n&&s[i]==s[i+1]&&s[i]==s[i+2]&&s[i]==s[i+3]&&s[i]==s[i+4]&&s[i]==s[i+5])
            {
                i+=5;
                tmp_len+=5;
                while(s[i]==s[i+1]&&i+1<n)i++,tmp_len++;
            }
            else i++;
            if(tmp_len==longest_len[s[i-1]]&&tmp_len)res+=3;
        }
        //注意every,测试点1和4会卡 
        for(int i=0;i+1<n;)
        {
            if(s[i]=='a'&&s[i+1]=='e'||s[i]=='a'&&s[i+1]=='h')
            {
                res-=4;
                i+=2;
            }
            else i++;
        }
        
        for(int i=0;i<n;)
        {
            if(i+3<n&&s[i+1]==s[i]+1&&s[i+2]==s[i]+2&&s[i+3]==s[i]+3)
            {
                res+=5;
                i+=3;
                while(s[i+1]==s[i]+1&&i+1<n)i++;
            }
            else i++;
        }
        
        if(res>t) cout<<res<<"!!!"<<endl;
        else cout<<res<<endl;
    }
    return 0;
} 
View Code

7-2 The First K Largest Numbers (25 分)

#include<bits/stdc++.h>
using namespace std;
//存1e6会内存超限 
int a[100];
bool cmp(int n1,int n2)
{
    return n1>n2;
}
int main()
{
    int n,k;
    //cin会超时 
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        //只存前k+1个数并进行排序,很经典的面试题~ 
        //优先队列、multiSet、map等都可以过这题,try a try 
        int tmp=min(i,k+1);
        scanf("%d",&a[tmp]);
        sort(a+1,a+tmp+1,cmp);
    }
    for(int i=1;i<=k&&i<=n;i++)
    {
        if(i==1)printf("%d",a[i]);
        else printf(" %d",a[i]);
    }
    printf("\n");
    
    return 0;
} 
View Code

7-3 Is It A Binary Search Tree - Again (25 分)

#include<bits/stdc++.h>
using namespace std;
int n,t[2050];
int a[2050],len=1;
//二叉搜索树的中序变历为升序 
void inOrder(int cur)
{
    if(t[cur]==-1||cur>n)return;
    inOrder(cur*2);
    a[len++]=t[cur];
    inOrder(cur*2+1);
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)cin>>t[i];
    inOrder(1);
    
    int b[2050]={0};
    for(int i=1;i<len;i++)b[i]=a[i];
    sort(b+1,b+len);
    
    //用b(排序后的a)判断a是否为升序 
    bool flag=0;
    for(int i=1;i<len;i++)
    {
        if(b[i]!=a[i])flag=1;
    }
    if(!flag)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    
    for(int i=1;i<len;i++)
    {
        if(i==1)cout<<a[i];
        else cout<<" "<<a[i];
    }
    cout<<endl;
    return 0;
}
View Code

7-4 The Rescue (30 分)

/*        
        0
        ↑
    3←       →1
        ↓
        2 

    ?为人所在位置 
    有三个距离最远(4)位置,pick了代码最small的,给了他0011指令
        ?#???
        ??X??
        ??##?
        ???#?
    起初图中所有0点都可能有人,所有人执行指令0011后(撞墙不走、到X不走),可能在四个?点处 
        ?#OO?
        OOXO?
        OO##O
        OO?#O
    pick了距离最远(4)的最下面一排的问号,给了他3001指令...... 
    
    
    ans的本质是:所以遍布在各个位置的人,听到这些指令后一一执行,或早或晚最后都能到X这个位置 

*/

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f;
char p[105][105];
int len[105][105],vis[105][105];
typedef pair<int, int> PII;
map<PII,int> is_hiker;

struct node
{
    int x,y; 
    //{x,y}到X的路 
    string path;
};

//先搜出x到所有0的距离 
void bfs(int x,int y)
{
    memset(vis,0,sizeof vis); 
    queue<PII>q;
    q.push({x,y});
    vis[x][y]=1;
    while(!q.empty())
    {
        PII cur=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int tx=cur.first,ty=cur.second;
            if(i==0)tx--;
            if(i==1)ty++;
            if(i==2)tx++;
            if(i==3)ty--;
            if(!vis[tx][ty]&&is_hiker[{tx,ty}])
            {
                vis[tx][ty]=1;
                len[tx][ty]=len[cur.first][cur.second]+1;
                q.push({tx,ty});
            }
        }
    }
}

//求出{x,y}到x的最small的路,反之求不出来 
string cal_path(int x,int y)
{
    memset(vis,0,sizeof vis);
    queue<struct node> q;
    struct node start={x,y,""};
    q.push(start);
    vis[x][y]=1;
    while(true)
    {
        struct node cur=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int tx=cur.x,ty=cur.y;
            if(i==0)tx--;
            if(i==1)ty++;
            if(i==2)tx++;
            if(i==3)ty--;
            if(!vis[tx][ty]&&p[tx][ty]!='#')
            {
                vis[tx][ty]=1;
                char ch='0'+i;
                if(p[tx][ty]=='X')return cur.path+ch;
                struct node nex={tx,ty,cur.path+ch};
                q.push(nex);
            }
        }
    }
}

//模拟从{tx,ty}按照s指令会走到哪个位置 
pair<int, int> walk(int tx,int ty,string s)
{
    for(int i=0;i<s.size();i++)
    {
        //遇墙不走 
        if(s[i]=='0'&&p[tx-1][ty]!='#')tx--;
        if(s[i]=='1'&&p[tx][ty+1]!='#')ty++;
        if(s[i]=='2'&&p[tx+1][ty]!='#')tx++;
        if(s[i]=='3'&&p[tx][ty-1]!='#')ty--;
        //终点不走 
        if(p[tx][ty]=='X')return {tx,ty};
    }
    return {tx,ty};
}

int main()
{
    int n,m;
    cin>>n>>m;
    //把边围起来 
    int x,y;
    queue<PII> hiker_place;
    for(int i=0;i<=m+1;i++)p[0][i]='#',p[n+1][i]='#',len[0][i]=len[n+1][i]=INF;
    for(int i=0;i<=n+1;i++)p[i][0]='#',p[i][m+1]='#',len[i][0]=len[i][m+1]=INF;
    for(int i=1;i<=n;i++)
    {
        getchar();
        for(int j=1;j<=m;j++)
        {
            cin>>p[i][j];
            if(p[i][j]=='X')x=i,y=j;
            if(p[i][j]=='#')len[i][j]=INF;
            //hiker_place是人可能在的地方的队列集合,is_hiker是判断该点是否可能有人 
            if(p[i][j]=='O')hiker_place.push({i,j}),is_hiker[{i,j}]=1;
        }
    }
    //找X到O的最远距离 
    bfs(x,y);
        
    string ans="";
    while(!hiker_place.empty())
    {
        int max_len=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(len[i][j]==INF)continue;
                else if(is_hiker[{i,j}]&&len[i][j]>max_len)max_len=len[i][j];
            }
        }

        string tmp=""; 
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(is_hiker[{i,j}]&&len[i][j]==max_len)
                {
                    string path=cal_path(i,j);
                    if(tmp==""||path<tmp)tmp=path;
                }
            }
        }
        ans+=tmp;
        
        //清空人的位置,将该步所有人的可能位置按照tmp指令进行模拟,得到新的所有人的可能位置,赋值给queue及map 
        is_hiker.clear();
        queue<pair<int, int> > tmp_place;
        while(!hiker_place.empty())
        {
            pair<int, int> cur=hiker_place.front(),nex;
            hiker_place.pop();
            nex=walk(cur.first,cur.second,tmp);
            if(!is_hiker[nex]&&p[nex.first][nex.second]!='X')
            {
                is_hiker[nex]=1;
                tmp_place.push(nex);
            }
        }
        hiker_place=tmp_place;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

posted @ 2022-03-09 11:44  myrtle  阅读(663)  评论(2编辑  收藏  举报