PAT(甲级)2019年冬季考试

7-1 Good in C (20分)

在这里插入图片描述

题意:给定 26 字母的写法,每个由 7 × 5 7\times 5 7×5 的字符矩阵组成。给定一个字符串 s,让你输出 s 中的每个单词。

思路:将 26 个字母存在三维数组中。然后在 s 中找到所有的单词。最后根据单词构造这个答案。每次都指定好,每个字母的位置即可。

细节:单词由大写字母组成。小写字母也认为是分隔符。读准题意,别按自己的习惯处理。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;


char A[30][10][10];
char mp[10010][100];
int len[10010];

int main()
{
    for(int i=1; i<=26; ++i)
        for(int j=1; j<=7; ++j)
            scanf("%s",A[i][j]+1);
    getchar();
    vector<string> words;
    string s;
    getline(cin,s);
    int n=s.size(),j;

//    for(int i=0; i<n; ++i)
//        if(s[i]>='a'&&s[i]<='z') s[i]=s[i]-'a'+'A';

    for(int i=0; i<n; i=j)
    {
        if(s[i]>='A'&&s[i]<='Z')
        {
            j=i;
            while(j<n&&s[j]>='A'&&s[j]<='Z') j++;
            string word;
            for(int x=i; x<j; ++x) word+=s[x];
            words.push_back(word);
        }
        else j++;
    }

    int nn=words.size();
    int R=nn*7+nn-1;
    for(int i=1; i<=R; ++i)
        for(int j=1; j<=100; ++j)
            mp[i][j]=' ';
    int nowx=1,nowy;
    for(auto word: words)
    {
        nowy=1;
        int m=word.size();
        int col=m*5+m-1;
        for(auto c: word)
        {
            for(int i=1; i<=7; ++i)
            {
                for(int j=1; j<=5; ++j)
                    mp[nowx+i-1][nowy+j-1]=A[c-'A'+1][i][j];
                len[nowx+i-1]=col;
            }
            nowy+=6;
        }
        nowx+=8;
        mp[nowx-1][1]='\n';
    }
    for(int i=1; i<=R; ++i)
    {
        for(int j=1; j<=len[i]; ++j)
            printf("%c",mp[i][j]);
        puts("");
    }
    return 0;
}

7-2 Block Reversing (25分)

在这里插入图片描述
题意:给定一个链表,让你以 m 个为一块切割后,从后往前输出。

思路:没什么难度的题。

细节:有关链表的题目,不一定给的 n 个点都会用上。

#include <bits/stdc++.h>
#define fi first
#define se second
#define ll long long
using namespace std;
const int maxn=1e6+5;

struct Node
{
    int add,val,nxt;
} p[maxn];
vector<pair<int,int> > ans,vec,res[maxn];

int main()
{
    int s,n,m;
    cin>>s>>n>>m;
    for(int i=1; i<=n; ++i)
    {
        int s,t,v;
        cin>>s>>v>>t;
        p[s]= {s,v,t};
    }
    for(int i=s; i!=-1; i=p[i].nxt)
        vec.push_back({i,p[i].val});
    int cnt=0;
    for(int i=0; i<vec.size(); ++i)
    {
        if(i%m==0) cnt++;
        res[cnt].push_back({vec[i].fi,vec[i].se});
    }
    for(int i=cnt; i>=1; --i)
        for(auto x: res[i]) ans.push_back(x);
    m=ans.size();
    for(int i=0; i<m-1; ++i) printf("%05d %d %05d\n",ans[i].fi,ans[i].se,ans[i+1].fi);
    printf("%05d %d -1\n",ans[m-1].fi,ans[m-1].se);

    return 0;
}

7-3 Summit (25分)

在这里插入图片描述
题意:类似最大团,给定一个图,给定一些点,要求这些点之间都必须要有边相连。然后询问能否在加一些点。

思路:先 O ( n 2 ) O(n^2) O(n2) 检查 k 个点,是不是都有边相连。然后查询有没有其他点可以加入这个团。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n,m,k;
int mp[210][210];
void solve(int Case,set<int> st)
{
    bool ok1=1;
    for(auto u: st)
    {
        for(auto v: st)
        {
            if(u==v) continue;
            if(mp[u][v]==0)
            {
                ok1=0;
                break;
            }
        }
        if(!ok1) break;
    }
    if(!ok1) printf("Area %d needs help.\n",Case);
    else
    {
        for(int i=1; i<=n; ++i)
        {
            if(st.count(i)) continue;
            bool ok=1;
            for(auto v: st)
            {
                if(mp[i][v]==0)
                {
                    ok=0;
                    break;
                }
            }
            if(ok)
            {
                printf("Area %d may invite more people, such as %d.\n",Case,i);
                return;
            }
        }
        printf("Area %d is OK.\n",Case);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; ++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        mp[u][v]=mp[v][u]=1;
    }
    scanf("%d",&k);
    for(int i=1; i<=k; ++i)
    {
        int l;
        scanf("%d",&l);
        set<int> st;
        for(int j=1; j<=l; ++j)
        {
            int x;
            scanf("%d",&x);
            st.insert(x);
        }
        solve(i,st);
    }
    return 0;
}

7-4 Cartesian Tree (30分)

在这里插入图片描述
题意:给定一个原数组,要求构建笛卡尔树,输出层序遍历。
思路:送分。每次在 [ l , r ] [l,r] [l,r] 中找到最小值的位置,然后构建左右两边就好了。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n;
int a[maxn];
struct Node
{
	int val;
	Node* ls,* rs;
};
Node* build(int L,int R)
{
	if(L>R) return NULL;
	int mi=*min_element(a+L,a+R+1);
	int pos;
	for(pos=L;pos<=R;++pos)
		if(a[pos]==mi) break;
	Node* node=new Node;
	node->val=a[pos];
	node->ls=build(L,pos-1);
	node->rs=build(pos+1,R);
	return node;
}
vector<int> ans;
void bfs(Node* root)
{
	queue<Node*> q;
	q.push(root);
	while(!q.empty())
	{
		Node* t=q.front();
		q.pop();
		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]);
	Node* root=build(1,n);
	bfs(root);
	int m=ans.size();
	for(int i=1;i<=m;++i) printf("%d%c",ans[i-1],i==m?'\n':' ');
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值