ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

6.5 竞赛题目选讲

2022-01-25 22:00:08  阅读:123  来源: 互联网

标签:题目 name int 选讲 tree ++ 6.5 && buf


Undraw_the_Trees

点击查看笔者代码
#include<iostream>
#include<vector>
using namespace std;

const int maxn = 20000+5, maxl = 200+5;
int cnt = 0, sum = 0;
string tree[maxl];

struct Node{
  string name;
  vector<Node*> v;	 
} node[maxn];

Node* build(int p, int s, int e, string name) {
  Node* root = &node[cnt++];
  root->v.clear();
  root->name = name;
  if(p >= sum) return root;
  for(int i = s; i < e; i++) {
  	if(tree[p][i] != ' ' && tree[p][i] != '#' && tree[p][i] != '-' && tree[p][i] != '|') {
	  name = tree[p][i];
	  if(p+1 < sum && tree[p+1][i] == '|') {
	  	int ts, te;
	  	for(ts=i, te=i; ; ) { 
	  	  if(ts > -1 && tree[p+2][ts-1]=='-') ts--;
	  	  else if(te < tree[p+2].length() && tree[p+2][te+1]=='-') te++;
	  	  else break;
		}
		if(te > tree[p+3].length()-1) te = tree[p+3].length()-1;
		root->v.push_back(build(p+3, ts, te+1, name));
	  }else{
	  	root->v.push_back(build(p+3, -1, -1, name)); 
	  }	
	}
  }
  return root;
}

void print_tree(Node* root) {
  cout << root->name;
  cout << "(";
  for(int i = 0; i < root->v.size(); i++) print_tree(root->v[i]);
  cout << ")";
}

int main() {
//	freopen("test.in", "r", stdin);
//	freopen("test.out", "w", stdout);
  int t;
  cin >> t;
  while(t--) {
    cnt = sum = 0;
    string line;
	while(getline(cin, line) && line != "#") {
	  tree[sum++] = line;
	}  
	string name = " ";
    int pos = 0;
    for(; pos < sum; pos++) {
      for(int i = 0; i < tree[pos].length(); i++) 
	    if(tree[pos][i] != ' ') {
	      name = tree[pos][i];
		  break;
	    }
      if(name != " ") break;	
	}
	Node* root = build(pos+3, 0, tree[pos+3].length(), name);
	cout << "(";
	if(name != " ") print_tree(root);
	cout << ")";
    cout << endl;
  }
  return 0;
}

又是一道模拟题,笔者原先了解错了要求,因此一直WA,这边需要尤为注意的一个地方就是,'-'的覆盖范围可能超过下一个字符串的长度(如果按照笔者这样存储的话),此时需要进行特判修改
同时因为这是一道递归建树题目,并且对树没有修改,所以可以在递归建树的过程中直接进行输出,也就是根本不需要建树,只能说作者的思路更加清晰
做题目前最好给自己一些思考时间,更加看透问题的本质,否则后面会花费大量时间进行调试,得不偿失,越是看似简单的问题越要小心
作者分析道:直接在二维字符数组里面递归即可,无须建树,注意对空树的处理,以及结点标号可以是任意可打印字符。代码如下:

点击查看代码
#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;

const int maxn = 200 + 10;
int n;
char buf[maxn][maxn];

//递归遍历并且输出以字符buf[r][c]为根的树 
void dfs(int r, int c) {
  printf("%c(", buf[r][c]);
  if(r+1 < n && buf[r+1][c] == '|') { //有子树
    int i = c; 
  	while(i-1 >= 0 && buf[r+2][i-1] == '-') i--;//找“----”的左边界
	while(buf[r+2][i] == '-' && buf[r+3][i] != '\0') {
	  if(!isspace(buf[r+3][i])) dfs(r+3, i);//fgets读入的'\n'也满足isspace()//空白符指空格、水平制表、垂直制表、换页、回车和换行符,isspace函数的作用就是判断是否是空白符 
	  i++; 
	} 
  }
  printf(")");
}
/*
注意fgets的使用,fgets(char buf[], int n, stdin)从stdin中读取最多(n-1)个字符,注意fgets并不是读取一行才会停止,n的优先级在某些情况下高于换行
fgets读取到\n的时候会结束,如果此时还没有到n-1个字符,那么他会存储,也就是说fgets只是以\n作为终止条件之一,并不是其不会读取换行符,
这也是需要注意的地方 
*/ 
void solve() {
  n = 0;
  for(;;) {
  	fgets(buf[n], maxn, stdin);
  	if(buf[n][0] == '#') break; else n++;
  }
  printf("(");
  if(n) {
  	for(int i = 0; i < strlen(buf[0]); i++)
  	  if(buf[0][i] != ' ') { dfs(0, i); break; }
  }
  printf(")\n");
}

int main() {
  int T;
  fgets(buf[0], maxn, stdin);
  sscanf(buf[0], "%d", &T);
  while(T--) solve();
  return 0;
}

标签:题目,name,int,选讲,tree,++,6.5,&&,buf
来源: https://www.cnblogs.com/FlnButFly/p/15844603.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有