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;
}