每日打卡 2017.03.15 北大信科2017机试真题题解

注:除最后一题外均已在原题出处AC

每日打卡 2017.03.15 北大信科2017机试真题题解_第1张图片

题库链接:http://jmusoft.openjudge.cn/beida/

1.奖学金

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。

任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前五名名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分) 是:

7 279

5 279

这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是 279 (总分等于输入的语文、数学、英语三科成绩之和) ,但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:

5 279

7 279

则按输出错误处理,不能得分。

输入
包含n+1行: 

第1行为一个正整数n,表示该校参加评选的学生人数。 

第2到n+1行,每行有3个用空格隔开的数字,每个数字都在0到100之间。第j行的3个数字依次表示学号为 j-1 的学生的语文、数学、英语的成绩。每个学生的学号按照输入顺序编号为1~n (恰好是输入数据的行号减1)。 

所给的数据都是正确的,不必检验。

50%的数据满足:各学生的总成绩各不相同;
100%的数据满足: 6<=n<=300。
输出
共有5行,每行是两个用空格隔开的正整数,依次表示前5名学生的学号和总分。
样例输入
样例 #1:
6
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98

样例 #2:
8
80 89 89 
88 98 78
90 67 80
87 66 91
78 89 91
88 99 77
67 89 64
78 89 98

样例输出
样例 #1:
6 265
4 264
3 258
2 244
1 237

样例 #2:
8 265
2 264
6 264
1 258
5 258
来源
NOIP2007复赛 普及组 第一题

放一个其他学校oj上的可以提交的地址  http://www.acmicpc.sdnu.edu.cn/problem/show/1182

#include
#include
#include
#include
#define sf(a) scanf("%d", &a)
#define sfs(a) scanf("%s", a)
using namespace std;

int n;
const int MAXN = 300 + 5;

struct Node
{
	int num;
	int chi;
	int math;
	int eng;
	int tot;
}node[MAXN];

bool operator < (const Node&a, const Node&b)
{
	if(a.tot != b.tot) return a.tot > b.tot;
	if(a.chi != b.chi) return a.chi > b.chi;
	return a.num < b.num;
}

int main()
{
	//freopen("input.txt", "r", stdin);
	sf(n);
	for(int i = 0; i < n; i++)
	{
		node[i].num = i;
		sf(node[i].chi);
		sf(node[i].math);
		sf(node[i].eng);
		node[i].tot = node[i].chi + node[i].math + node[i].eng;
	}
	sort(node, node + n);
	for(int i = 0; i < 5; i++)
	{
		cout << node[i].num + 1 << ' ' << node[i].tot << endl;
	}
	return 0;
}


2.高次同余方程求解

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

解高次同余方程是数论里的一个基础问题。现在邀请你来解一个简单的高次同余方程,xk=1(mod n)。(注:xk=1(mod  n)的意思是xk除以n的余数为1)

数据范围:n和k是整数,且0 < k < n < 1000


输入
两个整数,分别为k和n。
输出
从小到大输出方程的所有满足0 < x < n的整数解x,每行输出一个。
样例输入
3 7
样例输出
124
提示
需要注意中间计算结果的可能范围。
(a * b) % p = ((a % p) * (b % p)) % p

样例输入:
398 702
样例输出
1
53
649
701

题库链接:http://chjsgl.openjudge.cn/practice/1040/

居然只能交gcc。。。。日了狗诶,只能大改成c语言了。但是上机考试是可以交g++的

#include
#include
#define sf(a) scanf("%d", &a)
#define sfs(a) scanf("%s", a)

int main()
{
	//freopen("input.txt", "r", stdin);
	
	int n, k;
	sf(k);
	sf(n);
	for(int x = 1; x < n; x++)
	{
		int p = x;
		for(int j = 1; j < k; j++)
		{
			p*= x;
			p%= n;
		}
		if(p == 1)
			printf("%d\n", x);
	} 
	return 0;
}


3.二维数组回形遍历

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

给定一个row行col列的整数数组array,要求从array[0][0]元素开始,按回形从外向内顺时针顺序遍历整个数组。如图所示:


输入
输入的第一行上有两个整数,依次为row和col。
余下有row行,每行包含col个整数,构成一个二维整数数组。
(注:输入的row和col保证0 < row < 100, 0 < col < 100)
输出
按遍历顺序输出每个整数。每个整数占一行。
样例输入
4 4
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
样例输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
来源
北京大学2009年医学部练习题

题库链接:http://chjsgl.openjudge.cn/practice/1033/

居然只能交gcc。。。。日了狗诶,只能大改成c语言了。但是上机考试是可以交g++的

#include
#include
#define sf(a) scanf("%d", &a)
#define sfs(a) scanf("%s", a)
#define MAXN 105

int p = 0;
int r, c;
int a[MAXN][MAXN];
int vis[MAXN][MAXN];

const int dr[] = {0, 1, 0, -1};
const int dc[] = {1, 0, -1, 0};

void dfs(int row, int col)
{
	vis[row][col] = 1;
	printf("%d\n", a[row][col]);
	if(row + dr[p] <= r && row + dr[p] >= 1 && col + dc[p] <= c && col + dc[p] >= 1 && !vis[row+dr[p]][col+dc[p]])
		dfs(row + dr[p], col + dc[p]);
	else
	{
		p++;
		p%= 4; 
		if(row + dr[p] <= r && row + dr[p] >= 1 && col + dc[p] <= c && col + dc[p] >= 1 && !vis[row+dr[p]][col+dc[p]])
			dfs(row + dr[p], col + dc[p]);
	}
}

int main()
{
	//freopen("input.txt", "r", stdin);
	
	sf(r);
	sf(c);
	for(int i = 1; i <= r; i++)
	{
		for(int j = 1; j <= c; j++)
		{
			sf(a[i][j]);
		}
	}
	dfs(1, 1);
	return 0;
}

4.Black Jack

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

21点是一种风靡全球的游戏。进行游戏需要一副扑克牌,牌面由2到10的数字、J、Q、K、A组成。

假设现在有你和另外一名玩家,手上分别有若干张牌,你需要通过比较双方手上的扑克牌牌面,来看谁赢得了本局游戏。

牌面分值如下:

(1)2、3、4、5、6、7、8、9:按照牌面的实际大小计算分值。

(2)10、J、Q、K:均以10点为计算分值。

(3)A:11点和1点2种记分方式。如果A计算为11点,会使得手中牌的总分值大于21点的话,则A计算为1点。如果手中有两张A,它们的分值可以不相同。

如果一名玩家手中仅有两张牌,并且一张为A,另一张为10、J、Q、K中的一张,则称为黑杰克(BLACKJACK)。

游戏胜负判定规则如下:(优先级依次降低)

1. 对手手中的牌大于21点则你获胜。

2. 你手中的牌大于21点则对方获胜。

3.黑杰克(BLACK JACK)>21点>其他点数,点数大的玩家获胜。

4.点数相同,包括同为黑杰克(BLACK JACK),记为平局。


输入
第一行是你手中的牌数n,接下来n行分别为你的牌面。下面一行是你对手手中的牌数m,接下来m行分别为对手的牌面。( 0 < n, m < 10)
输出
如果你获胜,则输出“win”;如果对手获胜,则输出“lose”;如果平局,则输出“draw”。
样例输入
2
A
10
3
5
10
6
样例输出
win


题库链接:http://chjsgl.openjudge.cn/practice/1044/

居然只能交gcc。。。。日了狗诶,只能大改成c语言了。但是上机考试是可以交g++的

#include  
#include  
#include  
#define sf(a) scanf("%d", &a)  
#define sfs(a) scanf("%s", a) 
#define MAXN 11
  
  
int bj(int k, int n, int m, int atot, int btot)  
{  
    if(k == 0)  
    {  
        if(n != 2 || atot != 21)return 0;  
    }  
    else  
    {  
        if(m != 2 || btot != 21)return 0;  
    }  
    return 1;  
}  
  
int main()  
{  
    //freopen("input.txt", "r", stdin); 
	
	int n, m;  
	int a[MAXN] = {0}, b[MAXN] = {0};  
	int atot = 0, btot = 0;  
	char str[4] = {0};   
    sf(n);  
    for(int i = 0; i < n; i++)  
    {  
        sfs(str);  
        if(strlen(str) == 2) a[i] = 10;  
        else  
        {  
            if(str[0] >= '2' && str[0] <= '9') a[i] = str[0] - '0';  
            else if(str[0] != 'A') a[i] = 10;  
            else a[i] = 1;  
        }  
        atot+= a[i];   
    }  
    sf(m);  
    for(int i = 0; i < m; i++)  
    {  
        sfs(str);  
        if(strlen(str) == 2) b[i] = 10;  
        else  
        {  
            if(str[0] >= '2' && str[0] <= '9') b[i] = str[0] - '0';  
            else if(str[0] != 'A') b[i] = 10;  
            else b[i] = 1;  
        }  
        btot+= b[i];   
    }  
    if(atot <= 11)  
    for(int i = 0; i < n; i++)  
    {  
        if(a[i] == 1)  
        {  
            a[i] = 11;  
            atot+= 10;  
            break;  
        }  
    }  
    if(btot <= 11)  
    for(int i = 0; i < m; i++)  
    {  
        if(b[i] == 1)  
        {  
            b[i] = 11;  
            btot+= 10;  
            break;  
        }  
    }  
    int ok = 0;  
    if(btot > 21)ok = 1;  
    else  
    {  
        if(atot > 21) ok = 2;  
        else  
        {  
            if(bj(0, n, m, atot, btot))  
            {  
                if(!bj(1, n, m, atot, btot)) ok = 1;  
            }  
            else  
            {  
                if(bj(1, n, m, atot, btot))  
                {  
                    if(!bj(0, n, m, atot, btot)) ok = 2;  
                }  
                else  
                {  
                    if(atot > btot) ok = 1;  
                    else if(atot < btot) ok = 2;  
                }  
            }  
        }  
    }  
    if(ok)  
    {  
        if(ok == 1)  
            printf("win\n");
        else  
            printf("lose\n"); 
    }  
    else  
    {  
        printf("draw\n");
    }  
    return 0;  
}  


5.我爱学习!

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

Y同学最近状态十分低落,因为期末来临,DDL压身,以致神思不属、茶饭不思,沉迷手机、无心学习。然而在水手机的时候,Y同学却发现,身边用功的同学好多,自己的时间线上满满的都是学霸们的动态。

“WA了好久终于AC啦!”

“忙完一个DDL终于又可以忙下一个……”

再看着自己一事无成的期末,Y同学觉得自己身上的罪恶感一点点地增大。

突然,Y同学灵机一动:“如果我的罪恶感到了一定程度,那么我就可以战胜自己的怠惰,与学习喜结连理了!”

于是,你身为Y同学的挚友,受Y同学之托要写一个小程序,通过标注出那些能刺激Y同学的词语,来帮助Y同学积累罪恶感。


首先,Y同学会给你一个词汇表,里面是能刺激到Y同学的词语,一共n个,每个词语都是区分大小写的英文单词,中间没有空格。

从Y同学的词汇表中,任取两个词语A、B,都能保证A不会是B的子串。

然后,你会得到Y同学的时间线上大家的动态,一共m条,每条都是一行句子,包括英文字母、标点符号和若干空格。

你的任务就是:根据词汇表的顺序,对于每个词语依次从前往后把句子中出现的该词语替换为等量的星号('*')。这样Y同学看到星号就知道自己的罪恶感该提升了。被替换的词语前后不一定有空格。

但是要注意,句子里其他的部分要保持原样,只有刺激性词语需要替换成星号。

已经替换成星号的部分无法再被替换。


输入
第一行是两个数字n(1 <= n <= 20)和m(1 <= m <= 20),中间用空格分隔。
接下来n行,每行一个英文单词,组成能刺激到Y同学的词汇表。单词区分大小写,长度最大为20。
再接下来m行,每行一个英文句子,句子里可能有英文字母、标点符号和若干空格,长度最大为100。
输出
你需要输出m行,每行是替换过的英文句子。
样例输入
5 3
deadline
jigai
exam
WrongAnswer
TimeLimitExceeded
I finished all my deadlines hhhhhhhh
Wow jigai examination is coming, excited!
what the **** is "WrongAnswer"???
样例输出
I finished all my ********s hhhhhhhh
Wow ***** ****ination is coming, excited!
what the **** is "***********"???
提示
如果在词汇表里按顺序有bab、bbb两个词,那么替换bbbabab的结果应该是bb***ab


题库链接:http://chjsgl.openjudge.cn/practice/1043/

居然只能交gcc。。。。日了狗诶,只能大改成c语言了。但是上机考试是可以交g++的

#include  
#include  
#include  
#define sf(a) scanf("%d", &a)  
#define sfs(a) scanf("%s", a)  
#define MAXN 22  

int zz(int p, int q, char a[][22], char* str, int len)  
{  
    int l = strlen(a[q]);  
    if(p + l>len)return 0;  
    for(int i = 0; i < l; i++)  
    {  
        if(str[p + i] != a[q][i]) return 0;  
    }  
    return 1;  
}  
  
int main()  
{  
   // freopen("input.txt", "r", stdin);  
    
	int n, m, len;  
	char a[MAXN][MAXN];  
	char str[102];  
	  
    scanf("%d %d\n", &n, &m);  
    for(int i = 0; i < n; i++)  
    {  
        gets(a[i]);  
    }  
    while(m--)  
    {  
        gets(str);  
        len = strlen(str);  
        for(int j = 0; j < n; j++)
        {
        	for(int i = 0; i < len; i++)
        	{
				if(zz(i, j, a, str, len))  
                {   
                    int tmp = strlen(a[j]);  
                    for(int k = 0; k < tmp; k++)
                    {
                    	str[i+k] = '*';
					}
					i += tmp - 1;
                }  
			}
		}
        printf("%s\n", str);  
    }  
    return 0;  
}  

6.水淹七军

(题目有歧义)

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

随着最后通牒的递出,C国的总攻也开始了,由于C国在地形上的优势,C国总司令下令采用水攻,剿灭A国最后的有生力量。 
地形图是一个M*N的矩阵,矩阵上每一个点都对应着当前点的高度。C国总司令将选择若干个点进行放水。根据水往低处流的特性,水可以往四个方向的流动,被淹的地方的水面高度便和放水点的高度一样。然而,A国不是一马平川的,所以总会有地方是淹没不到的。你的任务很简单,判断一下A国司令部会不会被淹没掉。 
我们将给你完整的地形图,然后给出A国司令部所在位置,给出C国将在哪几个点进行放水操作。你所需要的,就是给出A国司令部会不会被水淹。

输入
第一行:一个整数K,代表数据组数。 
对于每一组数据: 
第1行:符合题目描述的两个整数,M(0 < M <= 200)、N(0 < N <= 200)。 
第2行至M+1行:每行N个数,以空格分开,代表这个矩阵上的各点的高度值H(0 <= H <= 1000)。 
第M+2行:两个整数I(0 < I <= M)、J(0 < J <= N),代表司令部所在位置。 
第M+3行:一个整数P(0 < P <= M * N),代表放水点个数。 
第M+4行至M+P+4行:每行两个整数X(0 < X <= M)、Y(0 < Y <= N),代表放水点。
输出
对于每组数据,输出一行,如果被淹则输出Yes,没有则输出No。
样例输入
1
5 5
1 1 1 1 1
1 0 0 0 1
1 0 1 0 1
1 0 0 0 1
1 1 1 1 1
3 3
2
1 1
2 2
样例输出
No
提示
样例中左上角的位置是(1, 1),右上角的位置是(1, 5), 右下角的位置是(5, 5)

题库链接:http://jmusoft.openjudge.cn/beida/06/

这题在别的oj上样例是Yes,跑到这边是No。。。这题的意思应该是相等不能流,其他地方的意思是相等也能流,总之是样例太蠢的锅

#include  
#include  
#include  
#include  
#include  
#define sf(a) scanf("%d", &a)  
#define sfs(a) scanf("%s", a)  
using namespace std;  
  
int n, m, len, p;  
const int MAXN = 202;  
int a[MAXN][MAXN];  
int vis[MAXN][MAXN];  
int rp, cp;  
int rw, cw;  
const int dr[] = {1, 0, -1, 0};  
const int dc[] = {0, 1, 0, -1};  
  
void dfs(int row, int col)  
{  
    vis[row][col] = 1;  
    for(int i = 0; i < 4; i++)  
    {  
        int r = row + dr[i], c = col + dc[i];  
        if(r <= m && r >= 1 && c <= n && c >= 1 && vis[r][c] == 0 && a[row][col] > a[r][c])  
        {
        	a[r][c] = a[row][col];
        	dfs(r, c);  //此处题目有歧义,水往低处流不明  
		} 
    }  
}   
  
int main()  
{  
    //freopen("input.txt", "r", stdin);  
    int K, t1, t2;  
    sf(K);  
    while(K--)  
    {  
        memset(vis, 0, sizeof(vis));  
        sf(m);  
        sf(n);  
        for(int i = 1; i <= m; i++)  
        {  
            for(int j = 1; j <= n; j++)  
            {  
                sf(a[i][j]);  
            }  
        }  
        sf(rp);  
        sf(cp);  
        sf(p);  
        while(p--)  
        {  
            sf(t1);  
            sf(t2);  
            dfs(t1, t2);   
        }  
        printf("%s\n", (vis[rp][cp] == 0 ? "No" : "Yes")); 
    }  
    return 0;  
}  

7.鸡蛋的硬度

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

最近XX公司举办了一个奇怪的比赛:鸡蛋硬度之王争霸赛。参赛者是来自世 界各地的母鸡,比赛的内容是看谁下的蛋最硬,更奇怪的是XX公司并不使用什么精密仪器来测量蛋的硬度,他们采用了一种最老土的办法--从高度扔鸡蛋--来 测试鸡蛋的硬度,如果一次母鸡下的蛋从高楼的第a层摔下来没摔破,但是从a+1层摔下来时摔破了,那么就说这只母鸡的鸡蛋的硬度是a。你当然可以找出各种 理由说明这种方法不科学,比如同一只母鸡下的蛋硬度可能不一样等等,但是这不影响XX公司的争霸赛,因为他们只是为了吸引大家的眼球,一个个鸡蛋从100 层的高楼上掉下来的时候,这情景还是能吸引很多人驻足观看的,当然,XX公司也绝不会忘记在高楼上挂一条幅,写上“XX公司”的字样--这比赛不过是XX 公司的一个另类广告而已。 
勤于思考的小A总是能从一件事情中发现一个数学问题,这件事也不例外。“假如有很多同样硬度的鸡蛋,那么我可以用二分的办法用最少的次数测出鸡蛋 的硬度”,小A对自己的这个结论感到很满意,不过很快麻烦来了,“但是,假如我的鸡蛋不够用呢,比如我只有1个鸡蛋,那么我就不得不从第1层楼开始一层一 层的扔,最坏情况下我要扔100次。如果有2个鸡蛋,那么就从2层楼开始的地方扔……等等,不对,好像应该从1/3的地方开始扔才对,嗯,好像也不一定 啊……3个鸡蛋怎么办,4个,5个,更多呢……”,和往常一样,小A又陷入了一个思维僵局,与其说他是勤于思考,不如说他是喜欢自找麻烦。 
好吧,既然麻烦来了,就得有人去解决,小A的麻烦就靠你来解决了:)

输入
输入包括多组数据,每组数据一行,包含两个正整数n和m(1<=n<=100,1<=m<=10),其中n表示楼的高度,m表示你现在拥有的鸡蛋个数,这些鸡蛋硬度相同(即它们从同样高的地方掉下来要么都摔碎要么都不碎),并且小于等于n。你可以假定硬度为x的鸡蛋从高度小于等于x的地方摔无论如何都不会碎(没摔碎的鸡蛋可以继续使用),而只要从比x高的地方扔必然会碎。
对每组输入数据,你可以假定鸡蛋的硬度在0至n之间,即在n+1层扔鸡蛋一定会碎。
输出
对于每一组输入,输出一个整数,表示使用最优策略在最坏情况下所需要的扔鸡蛋次数。
样例输入
100 1
100 2
样例输出
100
14
提示
最优策略指在最坏情况下所需要的扔鸡蛋次数最少的策略。
如果只有一个鸡蛋,你只能从第一层开始扔,在最坏的情况下,鸡蛋的硬度是100,所以需要扔100次。如果采用其他策略,你可能无法测出鸡蛋的硬度(比如你第一次在第二层的地方扔,结果碎了,这时你不能确定硬度是0还是1),即在最坏情况下你需要扔无限次,所以第一组数据的答案是100。
来源
习题(15-12)

题库链接:http://noi.openjudge.cn/ch0206/7627/

#include    
#include    
using namespace std;    

const int MAXBall=55,MAXFloor=1010;    
int DP[MAXBall][MAXFloor];    

int main()    
{    
    //freopen("input.txt","r",stdin);  
    for(int i=0;i<=1000;i++) DP[1][i]=i;    
    for(int i=2;i<=50;i++)    
        for(int j=1;j<=1000;j++)    
        {    
            if(i>j) DP[i][j]=DP[j][j];     
            else DP[i][j]=DP[i-1][j-1]+DP[i][j-1]+1;   
            if(DP[i][j]>1010) DP[i][j]=1010;    
        }    
    int n,th,ball,floor;    
    while(cin>>floor >> ball)  
        cout<

8.拓扑排序

总时间限制: 
10000ms 
内存限制: 
1000kB
描述

给出一个图的结构,输出其拓扑排序序列,要求在同等条件下,编号小的顶点在前

输入
若干行整数,第一行有2个数,分别为顶点数v和弧数a,接下来有a行,每一行有2个数,分别是该条弧所关联的两个顶点编号
输出
若干个空格隔开的顶点构成的序列(用小写字母)
样例输入
6 8
1 2
1 3
1 4
3 2
3 5
4 5
6 4
6 5
样例输出
v1 v3 v2 v6 v4 v5

题目链接:百练OJ题库4084

#include      
#include      
#include  
#define sf(a) scanf("%d", &a)   
using namespace std;      
  
int v, a;  
const int MAXN = 1005;   
  
struct Node  
{  
    int num;  
    int inv[MAXN];  
    int inn;  
}node[MAXN];  
  
int vis[MAXN];  
  
int main()      
{      
    //freopen("input.txt","r",stdin);    
    sf(v);  
    sf(a);  
    int t1, t2;  
    for(int i = 0; i < a; i++)  
    {  
        sf(t1);  
        sf(t2);  
        node[t2].inv[node[t2].inn++] = t1;  
    }  
    int tot = 0;  
    int flag = 1;  
    while(tot < v)  
    {  
        for(int i = 1; i <= v; i++)  
        {  
            if(vis[i] == 1)continue;  
            int ok = 1;  
            for(int j = 0; j < node[i].inn; j++)  
            {  
                if(vis[node[i].inv[j]] == 0)  
                {  
                    ok = 0;  
                    break;  
                }  
            }  
            if(ok == 1)  
            {  
                if(tot != 0)printf(" ");  
                vis[i] = 1;  
                printf("v%d", i);  
                tot++;  
                break;
            }  
        }  
    }  
    printf("\n");  
    return 0;  
} 



9.树的转换

总时间限制: 
5000ms 
内存限制: 
65536kB
描述

我们都知道用“左儿子右兄弟”的方法可以将一棵一般的树转换为二叉树,如:

    0                             0
  / | \                          /
 1  2  3       ===>             1
   / \                           \
  4   5                           2
                                 / \
                                4   3
                                 \
                                  5

现在请你将一些一般的树用这种方法转换为二叉树,并输出转换前和转换后树的高度。

输入
输入包括多行,最后一行以一个#表示结束。
每行是一个由“u”和“d”组成的字符串,表示一棵树的深度优先搜索信息。比如,dudduduudu可以用来表示上文中的左树,因为搜索过程为:0 Down to 1 Up to 0 Down to 2 Down to 4 Up to 2 Down to 5 Up to 2 Up to 0 Down to 3 Up to 0。
你可以认为每棵树的结点数至少为2,并且不超过10000。
输出
对于每棵树,按如下格式输出转换前和转换后树的高度:
Tree t: h1 => h2
其中t是树的编号(从1开始),h1是转换前树的高度,h2是转换后树的高度。
样例输入
dudduduudu
ddddduuuuu
dddduduuuu
dddduuduuu
#
样例输出
Tree 1: 2 => 4
Tree 2: 5 => 5
Tree 3: 4 => 5
Tree 4: 4 => 4

题库链接:POJ3437  http://poj.org/problem?id=3437

#include    
#include    
#include    
#include    
#include    
#define sf(a) scanf("%d", &a)    
#define sfs(a) scanf("%s", a)    
using namespace std;    
    
int n, k;    
const int MAXN = 40000 + 5;    
char str[MAXN];    
char p[MAXN];    
int len;    
    
struct Node    
{    
    int cc;    
    Node *lchild, *rchild;    
    Node():lchild(NULL), rchild(NULL) {}    
};    
    
void del(Node *root)    
{    
    if(root != NULL)    
    {    
        del(root->lchild);    
        del(root->rchild);    
        delete root;    
    }    
}    
    
int z;    
Node* build()    
{    
    if(p[z++] == 'u')    
    {    
        return NULL;    
    }    
    else    
    {    
        Node* ret = new Node();    
        ret->cc = z;    
        ret->lchild = build();    
        ret->rchild = build();    
        return ret;    
    }    
}    
    
int depth(Node *root)    
{    
    if(root == NULL) return 0;    
    else return max(depth(root->lchild), depth(root->rchild)) + 1;    
}    
    
int main()    
{    
   // freopen("input.txt", "r", stdin);    
    int kase = 0;    
    while(sfs(str) != EOF)    
    {    
        int d1 = 0;    
        len = strlen(str);    
        if(len == 1)break;    
        int tmp = 0;    
        p[0] = 'd';    
        for(int i = 0; i < len; i++)    
        {    
            p[i+1] = str[i];    
            if(str[i] == 'd')    
            {    
                tmp++;    
                if(tmp > d1) d1 = tmp;    
            }    
            else    
                tmp--;    
        }    
        p[len+1] = 'u';    
        p[len+2] = 'u';    
        z = 0;    
        Node *root = build();    
        printf("Tree %d: %d => %d\n", ++kase,d1, depth(root) - 1);  
        //printf("%d => %d\n", d1, depth(root) - 1);  
       // del(root);   
    }    
    return 0;    
}    


10.Strange Card Game


你可能感兴趣的:(每日打卡)