PAT 2019 冬季 12月 考试题解

总的而言这次考试很简单,要是今年的能跟这次一样简单就好了,可惜会加难度

Good in C

模拟题
一个小tip,可以将最后一行非大写字符都先换成空格,再用istringsteam读入

#include <bits/stdc++.h>
using namespace std;
vector<string>v[200];
int  main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt","r",stdin);
#endif
    string line,words,tmp;
    vector<string>word;
    for (int i = 'A'; i <= 'Z'; ++i) {
        for (int j = 0; j < 7; ++j) {
            getline(cin,line);
            v[i].push_back(line);
        }
    }
    getline(cin,words);
    for (int i = 0; i < words.size(); ++i) {
        if(!('A'<=words[i]&&words[i]<='Z'))words[i]=' ';
    }
    istringstream in(words);
    while (in>>tmp){
        word.push_back(tmp);
    }
    bool lineflag=false;
    for(string x:word){
        if(lineflag)cout<<endl;
        else lineflag=true;
        for (int i = 0; i < 7; ++i) {
            bool flag=false;
            for(char c:x){
                if(flag)cout<<" ";
                else flag=true;
                cout<<v[c][i];
            }
            cout<<endl;
        }
    }
    return 0;
}

Block Reversing

链表分块再翻转,题库有类似的
用vector<vector<int>>v;充当分块
翻转v再遍历一次就可以得到所需的顺序
注释是最开始的做法,最后一个点过不了,我现在都不知道为啥,在这卡了半天
一种方法实在过不了就想想能不能换方法重做一次,重做可能比debug更快

#include <bits/stdc++.h>
using namespace std;
int st,n,k,lastst=-1,lastlastst;
struct Node{
    int add,data,next;
}no[100010];
vector<vector<int>>v;
int  main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt","r",stdin);
#endif
    scanf("%d%d%d",&st,&n,&k);
    int id;
    for (int i = 0; i < n; ++i) {
        scanf("%d",&id);
        scanf("%d%d",&no[id].data,&no[id].next);
        no[id].add=id;
    }
    for(;st!=-1;){
        vector<int>tmp;
        for (int i = 0; i < k&&st!=-1; ++i,st=no[st].next) {
            tmp.push_back(st);
        }
        v.push_back(tmp);
    }
    reverse(v.begin(),v.end());
    vector<int>idx;
    for(auto x:v){
        for(auto y:x){
            idx.push_back(y);
        }
    }
    for (int i = 0; i < idx.size(); ++i) {
        if(i==idx.size()-1){
            printf("%05d %d -1\n",no[idx[i]].add,no[idx[i]].data);
        } else{
            printf("%05d %d %05d\n",no[idx[i]].add,no[idx[i]].data,no[idx[i+1]].add);
        }
    }

    /*int cnt=0;
    for (int i = 0; i < n; ++i) {
        cnt++;
        int next=no[st].next;
        if(cnt==1)lastlastst=no[st].add;
        if(cnt==k||no[st].next==-1){
            no[st].next=lastst;
            lastst=lastlastst;
            cnt=0;
        }
        st=next;
    }
//    cout<<lastlastst<<" "<<lastst<<endl;
    st=lastlastst;
    for (int i = 0; i < n; ++i) {
        if(no[st].next<0||i==n-1){
            printf("%05d %d -1\n",no[st].add,no[st].data);
        } else{
            printf("%05d %d %05d\n",no[st].add,no[st].data,no[no[st].next].add);
        }
        st=no[st].next;
    }*/
    return 0;
}

Summit

题库里也有类似的题, Maximum Clique
这不是并查集!!!
每个元素可能同时属于不同集合,不能当并查集做,这次还是犯了之前做Maximum Clique一样的错误,还得把之前做的题好好回顾一下。
由于N并不是很大,最大200,所以完全可以遍历暴力解决。
用flag标识一下不同情况。
首先判断area中有没有不连通的,再判断不在area中的元素是不是跟已在area中的所有元素连通。

#include<bits/stdc++.h>
using namespace std;
int n,m,u,v,small;
const int maxn=1000;
vector<int>area;
unordered_set<int>s;
bool conn[maxn][maxn];
int flag;
void judge(){
    bool notAll=false;
    for (int i = 1; i <= n; ++i) {
        if(s.count(i)==0){
            bool allconn=true;
            for(int x:area){
                if(!conn[i][x]){
                    allconn= false;
                }
            }
            if(allconn){
                small=i;
                flag=2;
                return;
            }
        }

    }
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("2.txt","r",stdin);
#endif
    cin>>n>>m;
    for (int i = 0; i < m; ++i) {
        cin>>u>>v;
        conn[u][v]=conn[v][u]=true;
    }
    cin>>m;
    int tmp;
    for (int i = 1; i <= m; ++i) {
        int k;
        cin>>k;
        flag=0;//ok
        area.clear();
        for (int j = 0; j < k; ++j) {
            cin>>tmp;
            if(flag==0){
                for(int x:area){
                    if(!conn[x][tmp]){
                        flag=1;//help
                    }
                }
                if(flag==0)area.push_back(tmp);
            }
        }
        if(flag==0){
            s.clear();
            s.insert(area.begin(),area.end());
            judge();
        }
        if(flag==0){
            cout<<"Area "<<i<<" is OK."<<endl;
        } else if(flag==1){
            cout<<"Area "<<i<<" needs help."<<endl;
        } else{
            cout<<"Area "<<i<<" may invite more people, such as "<<small<<"."<<endl;
        }
    }
    return 0;
}

Cartesian Tree

简单题,递归建树就完事了。
每个子序列中最小的元素就是根,根左侧、右侧的子序列再分别递归建树。

#include <bits/stdc++.h>
using namespace std;
int n,v[100],idx=0;
struct Node{
    int data,lchild=-1,rchild=-1;
}no[100];
int newnode(int val){
    no[idx].data=val;
    no[idx].lchild=no[idx].rchild=-1;
    return idx++;
}
int build(int s,int e){
    if(s>e)return -1;
    int k,m=INT_MAX;
    for (int i = s; i <= e; ++i) {
        if(v[i]<m){
            k=i;
            m=v[i];
        }
    }
    idx++;
    int root=newnode(m);
    no[root].lchild=build(s,k-1);
    no[root].rchild=build(k+1,e);
    return root;
}
bool flag=false;
void bfs(int root){
    queue<int>q;
    q.push(root);
    while (!q.empty()){
        int now=q.front();
        if(flag)cout<<" ";
        else flag=true;
        cout<<no[now].data;
        q.pop();
        if(no[now].lchild!=-1)q.push(no[now].lchild);
        if(no[now].rchild!=-1)q.push(no[now].rchild);
    }
}
int  main(){
#ifdef ONLINE_JUDGE
#else
    freopen("2.txt","r",stdin);
#endif
    cin>>n;
    for (int i = 0; i < n; ++i) {
        cin>>v[i];
    }
    int root=build(0,n-1);
    bfs(root);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值