PAT(甲级)2017年春季考试
PAT 1124 Raffle for Weibo Followers (20 分)
【解题思路】
微博抽奖,输入给定第一个中奖用户编号,以及后面每隔多少个用户给一个奖。
用一个循环输入,记录当前是第几条记录,判断当前用户是否中奖,输出即可。
需要注意的是,已经中奖的用户不再重复中奖,我们使用一个set,将中奖用户加入,如果后面遇到相同的字符串则跳过。
【满分代码】
#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int m,n,s,temp=0;
string t;
set<string> st;
cin>>m>>n>>s;
while(m--)
{
cin>>t;
if(st.count(t)==0)
temp++;
else continue;//没加上这句也能过,测试数据有漏洞
if(temp-s>=0&&(temp-s)%n==0)
{
cout<<t<<endl;
st.insert(t);
}
}
if(st.size()==0)
cout<<"Keep going..."<<endl;
return 0;
}
PAT 1125 Chain the Ropes (25 分)
【解题思路】
每次选取两根绳子,各自做成环后套在一起,即得到的新绳子长度为原来两段绳长之和的一半。
显然,越长的绳子被折的次数越少越好。
我们采用贪心,每次选取最短的两条绳合并,最终得到的一条即为最优答案。
这里我们采用优先队列,当然直接用数组排序,从头到尾处理也可。因为,选取最短的两根绳长和的一半得到的新绳,和没使用过的绳相比,肯定还是最短的。
【满分代码】
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
double t;
priority_queue<double,vector<double>,greater<double>> q;
cin>>n;
while(n--)
{
cin>>t;
q.push(t);
}
while(q.size()>1)
{
double a=q.top();
q.pop();
double b=q.top();
q.pop();
q.push((a+b)/2);
}
cout<<(int)q.top()<<endl;
return 0;
}
PAT 1126 Eulerian Path (25 分) 欧拉路
【解题思路】
判断一个图是否存在欧拉路。
求出并输出每个点的度数。
注意还需要判断整个图是否连通。
当图连通,且每个点度数都为偶数,输出“Eulerian”。
当图连通,且有且只有两个点度数为奇数,输出“Semi-Eulerian”。
其他情况,输出“Non-Eulerian”。
【满分代码】
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int vis[505],d[505];//每个点的度数
vector<int> g[505];//邻接表
int n,m,u,v,sum=0,cnt=0;
void dfs(int t)
{
sum++;
vis[t]=1;
for(int i=0;i<g[t].size();i++)
if(!vis[g[t][i]])
dfs(g[t][i]);
}//判断整个图是否连通
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
while(m--)
{
cin>>u>>v;
g[u].emplace_back(v);
g[v].emplace_back(u);
d[u]++;
d[v]++;
}
for(int i=1;i<=n;i++)
{
if(d[i]%2) cnt++;
i!=1?cout<<' '<<d[i]:cout<<d[i];
}
dfs(1);
if(sum==n&&cnt==0)
cout<<endl<<"Eulerian"<<endl;
else if(sum==n&&cnt==2)
cout<<endl<<"Semi-Eulerian"<<endl;
else
cout<<endl<<"Non-Eulerian"<<endl;
return 0;
}
PAT 1127 ZigZagging on a Tree (30 分) 二叉树
【解题思路】
经典的二叉树问题。
输入给出二叉树的中序遍历和后序遍历,要求输出层序遍历。
输出还有个要求,按照“Z”字形,奇数层从右往左,偶数层从左往右(这里把根节点作为第1层)。
我们在BFS层序遍历的时候,将每一层的结点存入vector中,输出的时候按照层数的奇偶来输出就可以了。
【满分代码】
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
using namespace std;
int in[35],post[25];
vector<int> vec[35];
struct node
{
int data;
node *lchild,*rchild;
};
node* build(int postL,int postR,int inL,int inR)
{
if(postL>postR)
return NULL;
node *root=new node;
root->data=post[postR];
int k;
for(k=inL;k<=inR;k++)
if(in[k]==post[postR])
break;
int num=k-inL;
root->lchild=build(postL,postL+num-1,inL,k-1);
root->rchild=build(postL+num,postR-1,k+1,inR);
return root;
}//递归建二叉树
void BFS(node* root)
{
cout<<root->data;//输出根节点的值
queue<node*> q;
q.push(root);
int level=0;//当前层数(根节点为第1层)
while(!q.empty())
{
level++;
int size=q.size();//当前层上的结点个数
while(size--)
{
node* t=q.front();
q.pop();
vec[level].emplace_back(t->data);
if(t->lchild)
q.push(t->lchild);
if(t->rchild)
q.push(t->rchild);
}
}
for(int i=2;i<=level;i++)
{
if(i%2==0)//偶数层从左往右输出
{
for(int j=0;j<vec[i].size();j++)
cout<<" "<<vec[i][j];
}
else//奇数层从右往左输出
{
for(int j=vec[i].size()-1;j>=0;j--)
cout<<" "<<vec[i][j];
}
}
}//层序遍历并输出
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>in[i];
for(int i=0;i<n;i++)
cin>>post[i];
node *root=build(0,n-1,0,n-1);
BFS(root);
return 0;
}