時間限制:10000msphp
單點時限:1000msnode
內存限制:256MBios
描述算法
在參與過了美食節以後,小Hi和小Ho在別的地方又玩耍了一陣子,在這個過程當中,小Ho獲得了一個很是有意思的玩具——一棵由小球和木棍鏈接起來的二叉樹!數組
小Ho對這棵二叉樹愛不釋手,因而給它的每個節點都標記了一個標號——一個屬於A..Z的大寫字母,而且沒有任意兩個節點的標號是同樣的。小Hi也瞅準了這個機會,從新鞏固了一下小Ho關於二叉樹遍歷的基礎知識~就這樣,日子安穩的過了兩天。app
這天,小Ho正好在求解這棵二叉樹的前序、中序和後序遍歷的結果,可是卻在求出前序遍歷和中序遍歷以後不當心把二叉樹摔到了地上,小球和木棍等零件散落了一地!ide
小Ho損失了心愛的玩具,正要嚎啕大哭起來,所幸被小Hi發現了,勸說道:「彆着急,這不是零件都還在麼?拼起來不就是了?」oop
「但是我忘記了二叉樹長什麼樣子了!」小Ho沮喪道。post
「這個簡單,你不是剛剛求出了這棵二叉樹的前序和中序遍歷的結果麼,利用這兩個信息就能夠還原出整棵二叉樹來哦!」測試
「這樣麼?!!」小Ho止住了淚水,問道:「那要怎麼作呢?」
沒錯!小Ho在這一週遇到的問題即是:給出一棵二叉樹的前序和中序遍歷的結果,還原這棵二叉樹並輸出其後序遍歷的結果。
「這可就要從頭提及了,咱們先找一棵二叉樹做爲例子吧!」小Hi在紙上畫了畫,遞給了小Ho。
「不妨假設你的二叉樹長成這個樣子~」小Hi道。
「但是個人二叉樹並非長成這個樣子啊!雖然我讀書少,可是你不要騙我好很差!」小Ho一臉氣憤道。
「我都說了是假設!是爲了能讓你明白如何通用的去解決這樣的問題!」小Hi無奈道。
「好吧……你接着說。」小Ho算是承認了這個說法。
「那麼對於這棵二叉樹,你先來計算一下它的前序遍歷和中序遍歷的結果吧!」小Hi也是絕不含糊就開始下發任務。
「唔……前序遍歷是ABDEGHCFIJ,中序遍歷……我想一想啊……是DBGEHACIJF!」小Ho並無花費多長時間就給出了答案。
「你還記得前序遍歷的遞歸定義麼?」小Hi點了點頭又繼續問道。
「是‘根節點’+‘左子樹的前序遍歷’+‘右子樹的前序遍歷’!」小Ho堅決果斷的答道:「而在這裏體現出來就是‘A'+‘BDEGH’+‘CFIJ’」。
「那中序遍歷呢?」小Hi繼續問道。
「是‘左子樹的中序遍歷’+‘根節點’+‘右子樹的中序遍歷’!在這裏也就是‘DBGEH’+‘A’+‘CIJF’。」小Ho此次花的時間更少了。
「還記得動態規劃時候咱們通常處理的方法麼?咱們這裏也能夠這樣作哦,若是咱們定義post_order(str1, str2)爲一棵前序遍歷的結果爲str1,中序遍歷的結果爲str2的二叉樹的後序遍歷的結果的話,咱們有沒有辦法把它化解成爲子問題呢?」小Hi道。
「讓我想一想……」小Ho拿出紙筆開始演算起來:「若是我要求解post-order(str1, str2)的話,首先不難發現,根據‘前序遍歷’str1=‘根節點’+‘左子樹的前序遍歷’+‘右子樹的前序遍歷’,我能夠知道這棵二叉樹的根節點root即是str1的第一個字符!」小Ho道。
「而我在知道了‘根節點’root以後,我即可以利用‘中序遍歷’str2=‘左子樹的中序遍歷’+‘根節點’+‘右子樹的中序遍歷’,求解出‘左子樹的中序遍歷’str2L和‘右子樹的中序遍歷’str2R!」
「接下來,因爲一棵子樹的前序遍歷和中序遍歷的長度相同,那麼仍然是根據‘前序遍歷’str1=‘根節點’+‘左子樹的前序遍歷’+‘右子樹的前序遍歷’,我能夠知道從str1的第2個字符開始的str2L.length()個字符即是‘左子樹的前序遍歷’str1L,而這以後的部分即是‘右子樹的前序遍歷’str1R!」小Ho說到這裏,頓了頓,但願從小Hi處獲得些反饋。
「沒錯!那你準備如何求解post_order(str1, str2)呢?」小Hi確定道。
「這隻要根據以前求出的結果,和‘後序遍歷’=‘左子樹的後序遍歷’+‘右子樹的後序遍歷’+‘根節點’,即可以知道——post_order(str1, str2)=post_order(str1l, str2l)+post_order(str1r, str2r)+root這樣一個式子來!而這個問題的規模——也就是二叉樹的大小,是一直在縮小的,因此是可以這樣不斷的劃分作下去的!也就是說我以後能夠將當前根節點的左子樹又拆分紅爲兩個問題來解決,一直到當前節點是葉子節點了爲止!而後慢慢的將這些答案拼成上層的問題的答案,而這個過程只須要使用遞歸完成就能夠了!」
「聽起來很容易的樣子呢!那你要不要趕忙去實現了算法,算出你的寶貝二叉樹長什麼樣呢?」小Hi滿意的點了點頭,隨即笑着問道。
「那是天然!」
輸入
每一個測試點(輸入文件)有且僅有一組測試數據。
每組測試數據的第一行爲一個由大寫英文字母組成的字符串,表示該二叉樹的前序遍歷的結果。
每組測試數據的第二行爲一個由大寫英文字母組成的字符串,表示該二叉樹的中序遍歷的結果。
對於100%的數據,知足二叉樹的節點數小於等於26。
輸出
對於每組測試數據,輸出一個由大寫英文字母組成的字符串,表示還原出的二叉樹的後序遍歷的結果。
樣例輸入
AB BA
樣例輸出
BA
這題能夠說是很微妙了,直接就把答案告訴你了。你直接轉化成代碼就行了
代碼:
#include<algorithm> #include<iostream> #include<cstring> #include<string> #include<cstdio> #include<vector> #include<stack> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; string post_order(string str1,string str2) { if(str1.length()<=0) return ""; //if(str1.length()) char c=str1[0]; int i=0,len=str2.length(); string str1l="",str2l="",str1r="",str2r=""; for(i=0;i<len;i++) { if(str2[i]==c) break; } str2l=str2.substr(0,i);//cout<<str2l<<endl; str2r=str2.substr(i+1);//cout<<str2r<<endl; str1l=str1.substr(1,str2l.length());//cout<<str1l<<endl; str1r=str1.substr(1+str2l.length());//cout<<str1r<<endl; return post_order(str1l,str2l)+post_order(str1r,str2r)+c; } int main() { string a,b; cin>>a>>b; cout<<post_order(a,b)<<endl; return 0; }
http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1960
Submit Page Summary Time Limit: 3 Sec Memory Limit: 128 Mb Submitted: 282 Solved: 134
有一棵由N個結點構成的樹,每一條邊上都有其對應的權值。如今給定起點,求從該點出發的一條路徑(至少有一條邊)使得這條路徑上的權值之和最大,並輸出這個最大值。
第一行一個正整數T,表明數據組數。每組數據第一行兩個正整數n(2<=n<=10^5),s(1<=s<=n),分別表示樹結點數目以及給定的起點,點的編號從1至N。接下來M行,每行三個整數x,y,z,(1<=x,y<=n,|z|<=1000),表明編號爲x和y的點之間有一條權值爲z的雙向邊。
每組數據輸出一行,即所找到路徑的最大權值(格式參見樣例)。
2 3 1 1 2 10 1 3 5 5 5 1 5 70 4 3 100 5 3 -10 2 5 60
Case #1: 10 Case #2: 90
2017年6月月賽-暨中南大學暑期集訓選拔賽第二場
xushu
bfs+鄰接表
#include<algorithm> #include<iostream> #include<cstring> #include<string> #include<cstdio> #include<vector> #include<stack> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; const int size=1e5+5; int first[size],nxt[size]; int flag[size]; struct node{ int b,e,v; }edge[size]; int tot; void roar_build(int id,int end,int value) { edge[tot].b=id; edge[tot].e=end; edge[tot].v=value; nxt[tot]=first[id]; first[id]=tot++; } const int INF=0x3f3f3f3f; int ans=0; void dfs(int n,int vl) { int id; if(first[n]==-1) return ; int val; for(int i=first[n];i!=-1;i=nxt[i]) { if(!flag[edge[i].e]) { id=edge[i].e; val=vl+edge[i].v; ans=max(ans,val); flag[edge[i].e]=1; dfs(id,val); flag[edge[i].e]=0; } } } int main() { int t; cin>>t; int cnt=0; while(t--) { tot=0; int s,n; memset(nxt,0,sizeof(nxt)); memset(first,-1,sizeof(first)); memset(flag,0,sizeof(flag)); ans=-INF; cin>>n>>s; flag[s]=1; for(int i=0;i<n-1;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); roar_build(x,y,z); roar_build(y,x,z); } dfs(s,0); printf("Case #%d: ",++cnt); cout<<ans<<endl; } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=2553
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 32936 Accepted Submission(s): 14174
Problem Description
在N*N的方格棋盤放置了N個皇后,使得它們不相互攻擊(即任意2個皇后不容許處在同一排,同一列,也不容許處在與棋盤邊框成45角的斜線上。
你的任務是,對於給定的N,求出有多少種合法的放置方法。
Input
共有若干行,每行一個正整數N≤10,表示棋盤和皇后的數量;若是N=0,表示結束。
Output
共有若干行,每行一個正整數,表示對應輸入行的皇后的不一樣放置數量。
Sample Input
1 8 5 0
Sample Output
1 92 10
Author
cgf
Source
dfs入門題,時間卡的好緊,因此先處理出答案記錄入數組。
#include<stdio.h> int n,locat[11]; long long solve; void check(int x) { int i,ok,q; if(x==n) solve++; else for(i=0;i<n;i++) { ok=1; locat[x]=i; for(q=0;q<x;q++) { if(locat[x]==locat[q]||x-locat[x]==q-locat[q]||locat[x]+x==locat[q]+q) {ok=0;break;} } if(ok==1) check(x+1); } } int main() { int solv[11]={0,1,0,0,2,10,4,40,92,352,724}; while(~scanf("%d",&n)) { if(n==0) break; printf("%d\n",solv[n]); } }
http://acm.hdu.edu.cn/showproblem.php?pid=1016
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 64943 Accepted Submission(s): 27877
Problem Description
A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime.
Note: the number of first circle should always be 1.
Input
n (0 < n < 20).
Output
The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order.
You are to write a program that completes above process.
Print a blank line after each case.
Sample Input
6 8
Sample Output
Case 1: 1 4 3 2 5 6 1 6 5 2 3 4 Case 2: 1 2 3 8 5 6 7 4 1 2 5 8 3 4 7 6 1 4 7 6 5 8 3 2 1 6 7 4 3 8 5 2
Source
Asia 1996, Shanghai (Mainland China)
素數環問題,經典dfs入門,須要注意的是最後須要判斷最後一個與第一個的關係
#include<algorithm> #include<iostream> #include<cstring> #include<string> #include<cstdio> #include<vector> #include<stack> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; int arr[25]; int flag[25]; int n; int check[]={1,3,5,7,11,13,17,19,23,29,31,37}; void pr() { int i=0; for(i;i<n;i++) { printf("%d",arr[i]); if(i!=n-1) printf(" "); else printf("\n"); } } int ok(int x,int y) { int z=x+y; int flag=0; for(int i=0;i<12;i++) { if(z==check[i]) flag=1; } return flag; } void dfs(int depth) { if(depth==n) { if(ok(arr[depth-1],1)) pr(); return; } else{ for(int i=0;i<12;i++) { int u=check[i]-arr[depth-1]; if(u>0&&!flag[u]&&u<=n) { flag[u]=1; arr[depth]=u; dfs(depth+1); flag[u]=0; } } } } int main() { int cnt=0; while(cin>>n) { memset(flag,0,sizeof(flag)); flag[1]=1; arr[0]=1; printf("Case %d:\n",++cnt); dfs(1); printf("\n"); } return 0; }
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 13573 Accepted Submission(s): 6327
Problem Description
A robot has been programmed to follow the instructions in its path. Instructions for the next direction the robot is to move are laid down in a grid. The possible instructions are
N north (up the page)
S south (down the page)
E east (to the right on the page)
W west (to the left on the page)
For example, suppose the robot starts on the north (top) side of Grid 1 and starts south (down). The path the robot follows is shown. The robot goes through 10 instructions in the grid before leaving the grid.
Compare what happens in Grid 2: the robot goes through 3 instructions only once, and then starts a loop through 8 instructions, and never exits.
You are to write a program that determines how long it takes a robot to get out of the grid or how the robot loops around.
Input
There will be one or more grids for robots to navigate. The data for each is in the following form. On the first line are three integers separated by blanks: the number of rows in the grid, the number of columns in the grid, and the number of the column in which the robot enters from the north. The possible entry columns are numbered starting with one at the left. Then come the rows of the direction instructions. Each grid will have at least one and at most 10 rows and columns of instructions. The lines of instructions contain only the characters N, S, E, or W with no blanks. The end of input is indicated by a row containing 0 0 0.
Output
For each grid in the input there is one line of output. Either the robot follows a certain number of instructions and exits the grid on any one the four sides or else the robot follows the instructions on a certain number of locations once, and then the instructions on some number of locations repeatedly. The sample input below corresponds to the two grids above and illustrates the two forms of output. The word "step" is always immediately followed by "(s)" whether or not the number before it is 1.
Sample Input
3 6 5 NEESWE WWWESS SNWWWW 4 5 1 SESWE EESNW NWEEN EWSEN 0 0
Sample Output
10 step(s) to exit 3 step(s) before a loop of 8 step(s)
Source
簡單dfs
代碼:
#include<algorithm> #include<iostream> #include<cstring> #include<string> #include<cstdio> #include<vector> #include<stack> #include<cmath> #include<queue> #include<set> using namespace std; char map[11][11]; int flag[11][11]; int situ[11][11]; int sx,sy,b; int check(int x,int y) { if(x>sx||x<1||y>sy||y<1) return 0; return 1; } void dfs(int x,int y,int befo) { if(check(x,y)) { if(flag[x][y]) { cout<<situ[x][y]-1<<" step(s) before a loop of "<<befo-situ[x][y]+1<<" step(s)"<<endl; return; } } else { cout<<befo<<" step(s) to exit"<<endl; return; } situ[x][y]=befo+1; //cout<<situ[x][y]<<' '<<befo<<endl; flag[x][y]=1; if(map[x][y]=='N') dfs(x-1,y,situ[x][y]); if(map[x][y]=='S') dfs(x+1,y,situ[x][y]); if(map[x][y]=='E') dfs(x,y+1,situ[x][y]); if(map[x][y]=='W') dfs(x,y-1,situ[x][y]); } int main() { while(~scanf("%d%d",&sx,&sy)) { if(!sx) break; cin>>b; memset(situ,0,sizeof(situ)); memset(flag,0,sizeof(flag)); int i; for(i=1;i<=sx;i++) { scanf("%s",map[i]+1); } dfs(1,b,0); //cout<<"x"<<endl; } return 0; }
Avoid The Lakes http://poj.org/problem?id=3620
Description Farmer John's farm was flooded in the most recent storm, a fact only aggravated by the information that his cows are deathly afraid of water. His insurance agency will only repay him, however, an amount depending on the size of the largest "lake" on his farm. Input * Line 1: Three space-separated integers: N, M, and K Output * Line 1: The number of cells that the largest lake contains. Sample Input 3 4 5 3 2 2 2 3 1 2 3 1 1 Sample Output 4 Source |
dfs對全圖遍歷,取出全部的塊的大小,取其中最大的
代碼:
#include<algorithm> #include<iostream> #include<cstring> #include<string> #include<cstdio> #include<vector> #include<stack> #include<cmath> #include<queue> #include<set> using namespace std; int map[105][105]; int flag[105][105]; int x0[10005],y0[10005]; int n,m,k; int mov[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; int check(int x,int y) { if(x>=1&&x<=n&&y>=1&&y<=m&&!flag[x][y]&&map[x][y]) return 1; else return 0; } int dfs(int x,int y) { int s=0; int sign=0; flag[x][y]=1; for(int i=0;i<4;i++) { int xx,yy; xx=x+mov[i][0]; yy=y+mov[i][1]; if(check(xx,yy)) { sign=1; s+=dfs(xx,yy); } } if(!sign)return 1; return s+1; } int main() { while(cin>>n>>m>>k) { memset(map,0,sizeof(map)); memset(flag,0,sizeof(flag)); int ans=0; for(int i=0;i<k;i++) { scanf("%d%d",&x0[i],&y0[i]); map[x0[i]][y0[i]]=1; } for(int i=0;i<k;i++) { if(!flag[x0[i]][y0[i]]) { ans=max(ans,dfs(x0[i],y0[i])); } //cout<<endl; } cout<<ans<<endl; } return 0; }