acm专题---dfs+bfs
题目来源:http://hihocoder.com/problemset/problem/1049
#1049 : 后序遍历
描述
在参与过了美食节之后,小Hi和小Ho在别的地方又玩耍了一阵子,在这个过程中,小Ho得到了一个非常有意思的玩具——一棵由小球和木棍连接起来的二叉树!
小Ho对这棵二叉树爱不释手,于是给它的每一个节点都标记了一个标号——一个属于A..Z的大写字母,并且没有任意两个节点的标号是一样的。小Hi也瞅准了这个机会,重新巩固了一下小Ho关于二叉树遍历的基础知识~就这样,日子安稳的过了两天。
这天,小Ho正好在求解这棵二叉树的前序、中序和后序遍历的结果,但是却在求出前序遍历和中序遍历之后不小心把二叉树摔到了地上,小球和木棍等零件散落了一地!
小Ho损失了心爱的玩具,正要嚎啕大哭起来,所幸被小Hi发现了,劝说道:“别着急,这不是零件都还在么?拼起来不就是了?”
“可是我忘记了二叉树长什么样子了!”小Ho沮丧道。
“这个简单,你不是刚刚求出了这棵二叉树的前序和中序遍历的结果么,利用这两个信息就可以还原出整棵二叉树来哦!”
“这样么?!!”小Ho止住了泪水,问道:“那要怎么做呢?”
没错!小Ho在这一周遇到的问题便是:给出一棵二叉树的前序和中序遍历的结果,还原这棵二叉树并输出其后序遍历的结果。
提示:分而治之——化大为小,化小为无输入
每个测试点(输入文件)有且仅有一组测试数据。
每组测试数据的第一行为一个由大写英文字母组成的字符串,表示该二叉树的前序遍历的结果。
每组测试数据的第二行为一个由大写英文字母组成的字符串,表示该二叉树的中序遍历的结果。
对于100%的数据,满足二叉树的节点数小于等于26。
输出
对于每组测试数据,输出一个由大写英文字母组成的字符串,表示还原出的二叉树的后序遍历的结果。
- 样例输入
-
AB BA
- 样例输出
-
BA
#include <iostream> using namespace std; #include <vector> #include<algorithm> #include<queue> #include<string> #include<map> #include<math.h> #include<iomanip> #include<stack> struct node{ char ch; node* left,*right; node(char _ch) { ch=_ch; left=NULL; right=NULL; } }; node* build(string prestr,string midstr,int len) { if(len<=0) { return NULL; } else { node* root=new node(prestr[0]); int idx=0; for(int i=0;i<len;i++) { if(prestr[0]==midstr[i]) { idx=i; break; } } root->left=build(prestr.substr(1,idx),midstr.substr(0,idx) , idx); root->right=build(prestr.substr(idx+1,len-idx-1), midstr.substr(idx+1,len-idx-1), len-idx-1); cout<<root->ch; return root; } } int main() { string prestr="",midstr=""; cin>>prestr>>midstr; node* root=build(prestr, midstr,prestr.length()); cout<<endl; return 0; } /* 124536 425136 */
题目来源:http://hihocoder.com/contest/ntest2015april/problem/3
题目3 : 连连看
描述
小江最喜欢玩的游戏"天下3"最近推出了连连看的小玩法。玩家可以将2个相同图案的牌子连接起来,连接线不多于3根线段(即最多拐2折),就可以成功将这对牌子消除。如示意图所示,红色,黄色和蓝色的消除都是合法的,因为它们分别需要2个,0个和1个折。而黑色的消除是不合法的,因为这对牌至少需要拐3个折才能连接起来。
但是小江并不满足于这个游戏规则,因为他觉得最多只能拐2折这个限制并不合理。好奇的小江想知道的是,给定一个连连看的状态以及某一个牌子,在K折以内可以到达的所有具有相同图案的牌子的数量是多少。
输入
每个输入数据包含多个测试点。
第一行为测试点的个数S <= 20。之后是S个测试点的数据。
每个测试点的第一行为1 <= N <= 200, 1 <= M <= 200,表示连连看的大小。接下来的N行,每一行有M个整数,表示连连看该行的状态,如果为0,则表示该格为空,否则代表一种图案的牌子。
然后是三个整数X <= N, Y <= M,0 <= K <= 10000,表示查询(X, Y)这个牌子在K折以内能消除的所有相同牌子总数。其中连连看左上角的格子坐标为(1, 1),右下角为(N, M)。保证查询的格子是有图案的。
输出
对于每个测试点,输出对应的能消除的所有牌子总数。
提示
样例第一个例子,第(1, 1), (2, 3)和(2, 5)为3个可以在3折内被消除的相同牌子。
- 样例输入
-
3 4 5 1 0 1 0 2 0 0 1 3 1 3 3 1 5 9 6 1 4 8 7 1 3 3 4 5 1 0 1 0 2 0 0 1 3 1 3 3 1 5 9 6 1 4 8 7 1 3 1 2 2 1 10 2 3 1 1 10
- 样例输出
-
3 2 0
#include<iostream> #include<algorithm> #include<vector> #include<string> #include<stack> #include<fstream> #include<queue> #include<string.h> #include<list> #include<map> using namespace std; int mymap[205][205]; bool vis[205][205]; struct point { int x; int y; int cnt; int cx; int cy; point(int _x,int _y,int _cnt,int _cx,int _cy) { x = _x; y = _y; cnt = _cnt; cx = _cx; cy = _cy; }; }; int m, n; bool isok(int newx, int newy,int value) { if (newx >= 0 && newy >= 0 && newx <= m+1&&newy <= n+1 && (mymap[newx][newy] == -1 || mymap[newx][newy] == 0 || mymap[newx][newy] == value)) { return true; } else { return false; } } int bfs(int start, int end, int k) { int a[4][2] = { { 0, -1 }, { 0, 1 }, { -1, 0 }, { 1, 0 } };//左右上下 int cntans = 0; queue<point> que; int value = mymap[start][end]; for (int i = 0; i < 4; i++) { int newx = start + a[i][0]; int newy = end + a[i][1]; if (isok(newx, newy,value)) { que.push(point(newx,newy,0,a[i][0],a[i][1])); } } vis[start][end] = true; while (!que.empty()) { point top = que.front(); que.pop(); vis[top.x][top.y] = true; if (mymap[top.x][top.y] == value) { cntans++; continue; } else { for (int i = 0; i < 4; i++) { int tmpx = top.x + a[i][0]; int tmpy = top.y + a[i][1]; if (isok(tmpx, tmpy, value)&&vis[tmpx][tmpy]==false) { if (!(top.cx == a[i][0] && top.cy == a[i][1]) && top.cnt >= k) continue; else if (!(top.cx == a[i][0] && top.cy == a[i][1])) { que.push(point(tmpx,tmpy,top.cnt+1,a[i][0],a[i][1])); } else { que.push(point(tmpx, tmpy, top.cnt, a[i][0], a[i][1])); } } } } } return cntans; } int main() { int t; cin >> t; for (int i = 0; i < t; i++) { cin >> m >> n; memset(vis, false, sizeof(vis)); for (int j = 0; j <= m+1; j++) { for (int k = 0; k <= n+1; k++) mymap[j][k] = -1; } for (int j = 1; j <= m; j++) { for (int k = 1; k <= n; k++) { cin >> mymap[j][k]; } } int x, y, k; cin >> x >> y >> k; cout << bfs(x, y, k) << endl; } } /* 3 4 5 1 0 1 0 2 0 0 1 3 1 3 3 1 5 9 6 1 4 8 7 1 3 3 4 5 1 0 1 0 2 0 0 1 3 1 3 3 1 5 9 6 1 4 8 7 1 3 1 2 2 1 10 2 3 1 1 10 3 2 0 */