2011年北邮计算机院复试上机题目
2011.计算机院.Problem A.反转单词
链接1: http://10.105.242.83/problem/136 链接2: http://10.105.242.80/problem/p/103
题目描述
给出一句英文句子(只由大小写字母和空格组成,不含标点符号,也不会出现连续的空格),请将其中的所有单词顺序翻转
输入格式
多组数据,以EOF结束。
每行一句英文句子(确保只由大小写字母和空格组成,不含标点符号,也不会出现连续的空格,字符串总长度1000以内)
输出格式
每组数据输出一行,为反转后的字符串
输入样例
It is a apple
输出样例
apple a is It
思路
没有多余空格 可以使用 cin 输入 自动跳过空格 并且将单词入栈。全部入栈后出栈即可
代码实现
#include <iostream>
#include <string>
#include <stack>
#include <cstdio>
using namespace std;
int main()
{
stack<string> s;
string str;
bool firstcase;
while( cin >> str )
{ ///Initstack
while( !s.empty() )
s.pop();
firstcase = true;
///Input
while(1)
{
s.push(str);
if( getchar() == '\n') ///因为 在cin 最后一个单词后 str被压入栈中 但是输入缓冲队列 还保存着 回车符 cin并不会丢弃回车符
break;
cin >> str;
}
///output
while( !s.empty() )
{
if( firstcase ) ///输出一个单词时,先输出空格,在输出单词, 当这个单词时第一个单词时,不输出空格
firstcase = false;
else
cout << " ";
str = s.top();
cout << str;
s.pop();
}
cout << endl;
}
return 0;
}
2011.计算机院.Problem B.912星球的研究生
链接1: http://10.105.242.83/problem/137 链接2: http://10.105.242.80/problem/p/104
题目描述
最近912星球的研究生入学了,912星球的教务处因此忙的焦头烂额,要求yzr做一个信息管理系统登陆查询研究生的考试成绩。但是yzr太弱了,你能帮帮忙么?
912星球的每一位研究生都有一个名字id和一份星球考研成绩,可喜的是都是自然数。
信息管理系统需要完成两个命令:
1.“Insert空格id_number空格score_number”命令,表示登陆一个名字id为id_number,分数为score_number的同学的信息。其中id和score都是自然数,分别代表一位研究生的id和成绩(中间有一个空格)。
2.“Find id_number”命令,表示查询一个名字id为id_number的研究生的成绩,需要输出对应的成绩
输入格式
首先输入一个整数T,表示一共有T组数据(0< T≤ 10)
每组数据的第一行包括一个数字n,表示这组数据一共n行,并且保证最多只有n位研究生,0< n≤ 100。
接下来每一行都有一条命令,形式如上所述。
不会有两名拥有同样名字id的同学,并且保证名字id是自然数且小于等于1000,得分为自然数且小于等于10000
输出格式
对于每一组数据中的每一条命令:
Insert命令无需任何对应输出
Find命令需要输出一行,形如“name:name_id空格score:score_number”,表示找到一个名字id为id_number,分数为score_number的同学的信息。如果没有找到输出“No result!”。
每个输出占一行,每组数据之间不用留空行
输入样例
2
2
Insert 0 10
Find 0
5
Insert 1 1
Find 2
Insert 2 2
Find 2
Find 1
输出样例
name:0 score:10
No result!
name:2 score:2
name:1 score:1
代码实现
#include <iostream>
using namespace std;
struct postgraduate
{
int id;
int score;
};
postgraduate stu[100];
int count;
int main()
{
int T, n, i, j;
string demand;
int _id, _score;
cin >> T;
while( T-- )
{
count = 0;
cin >> n;
for( i = 0; i < n; i++ )
{
cin >> demand;
if( demand == "Insert" )
{
cin >> _id >> _score;
stu[count].id = _id;
stu[count].score = _score;
count++;
}
else
{
cin >> _id;
for( j = 0; j < count; j++ )
if( stu[j].id == _id )
{
cout << "name:" << _id << " score:" << stu[j].score << endl;
break;
}
if( j == count )
cout << "No result!" << endl;
}
}
}
return 0;
}
2011.计算机院.Problem C.寻找宝藏
链接1: http://10.105.242.83/problem/138 链接2: http://10.105.242.80/problem/p/105
题目描述
有一棵多叉树T,你在树根处,宝藏在某一叶子节点L。现在你沿着树枝向叶子方向走去,从不回头,如果遇到树叉节点,你等概率地挑选一个分支继续走。请问,在给定T,L的情况下,你有多大概率拿到宝藏?
输入格式
第一行,整数N,M,L(1< N< 1000,0< M< 1000,0< L< N),分别代表树T上的节点数、树枝的个数,宝藏所在节点。树根为0号结点。
然后有M行,每行两个整数A,B(0≤ A,B< N)代表从节点A到节点B有一条树枝。可以假设节点A总是更靠近树根。
输出格式
所求的概率,输出四舍五入到6位小数,然后换行。
输入样例
6 5 5
0 1
1 3
0 2
2 4
2 5
输出样例
0.250000
代码实现
#include <iostream>
#include <vector>
#include <cstdio>
#include <cmath>
#define maxsize 1010
using namespace std;
/// 树模板 此种树结构 data 记录 双亲 ,sonList (vector) 记录 孩子,即一个节点中,既能够向上找双亲,也能够向下找孩子
typedef struct Node
{
int data; /// 节点值 为 父节点 所在数组 下标
vector<int> sonList;
bool turnOn; ///此二叉树节点是否有效
Node()
{
initNode();
}
void initNode()
{
turnOn = false;
sonList.clear();
}
};
Node Tree[maxsize]; ///用一维数组来存储一颗二叉树
//int degree[maxsize]; ///保存各个节点的度
///int cursor;
double p = 1;
bool visit[maxsize];
/*
int createNode( int data ) ///在树中插入一个节点值为data 的数据
{
if( cursor+1 == maxsize )
return false;
int nowp = cursor++;
Tree[nowp].data = data;
return nowp;
}
*/
int createNode( int data, int index ) ///在数组下标 x 处创造一个节点
{
Tree[index].data = data;
Tree[index].turnOn = true;
return index;
}
void createTree( int N )
{ /// Tree[]初始化
for( int i = 0; i < maxsize; i++ )
Tree[i].initNode();
///for( int i = 0; i < maxsize; i++ )
///degree[i] = 0;
///cursor = 0;
int x,y;
N--; /// 此树有N个节点,N-1条边
while( N-- )
{
cin >> x >> y; /// x 是 y 的父节点
///degree[x]++; /// 创建数组的同时同时统计节点的度
///degree[y]++;
if( Tree[x].turnOn == false ) /// X 节点没有创建 即 X 是根节点
createNode( -1, x );
Tree[x].sonList.push_back( y ); /// 创造节点后 记录孩子节点
if( Tree[y].turnOn == false )
createNode( x, y );
}
}
bool DFS( int index, int K ) ///从index 向下开始dfs
{
if( index == K )
return true;
visit[index] = true;
bool flag = false;
for( int i = 0; i < Tree[index].sonList.size(); i++ )
if( !visit[Tree[index].sonList[i]] )
{
flag = DFS( Tree[index].sonList[i], K );
if( flag )
{
p = p*1.0/Tree[index].sonList.size();
return true;
}
}
return false;
}
int main()
{
int N, M, K;
cin >> N >> M >> K;
createTree( N );
for( int i = 0; i < maxsize; i++ )
visit[i] = false;
DFS(0, K);
p = (int( p*1000000 + 0.5))/1000000.0;
printf("%0.6f\n", p);
return 0;
}
2011.计算机院.Problem D.公式推导
链接1: http://10.105.242.83/problem/139 链接2: http://10.105.242.80/problem/p/106
题目描述
数理逻辑是计算机科学中很重要的一环,而公式的自动推导就是这门科学的研究方向之一。虽然目前复杂的公式推导还难以做到,但一个简单的推导机器还是可以很容易实现的
一个“蕴含式”可以表示为 A --> B ,意为A可以推出B,其中A和B均为非空的条件的集合(在本题中每一个条件用单独的一个小写字母表示)。比如 abc --> de 表示如果条件a、b、c均成立则可以推出d、e都成立。
现已知有N个 推导规则。最后给出一条新的推导规则,在已知的情况,求最后一条规则是否成立
HINT对公式的读入建议使用scanf(“%s%*s%s”,a,b)
公式的推导基于Armstrong 公理,即满足:
自反律:若属性集Y 包含于属性集X,属性集X 包含于U,则X–>Y 在R 上成立。
增广律:若X –> Y 在R 上成立,且属性集Z 包含于属性集U,则XZ–>YZ 在R 上成立。
传递律:若X –> Y 和 Y –> Z在R 上成立,则X –> Z 在R 上成立。
输入格式
多组数据,以EOF结束。
每组数据的第一行为一个数N(0≤ N≤ 10000)
之后N行每行的形式为:条件集合A+空格+“–>”+空格+条件集合B,表示A可以推出B
集合中每一个小写字母表示一个条件(条件数不会超过26)
之后再来一行,表示推导结果(格式同上)
输出格式
每组数据输出一行,YES表示可以推导出,NO表示不能
输入样例
2
a --> bc
b --> d
a --> d
2
a --> b
a --> c
b --> c
输出样例
YES
NO
思路
这啥玩意??