這個學期選了一門演算法分析與設計,老師引入了ACM的題目讓我們實踐.說實在我對ACM的題目是挺感冒的,主要是因為感覺它離實際太遙遠,而且難學. 不過最近的學習讓我有了新的看法,在學習中適當地嘗試一點ACM題目(一直撲在這個上面我覺得就沒什麼意義了),確實能對自己的程式設計能力以及邏輯思維有較大的提高.也許是我接觸的題不多吧,我認為ACM提倡的思維就是"由繁到簡". 特別是它在樹上的做法真的很棒. 眾所周知,樹的遍曆是很花費時間的,一旦樹的高度不斷增大時,遍曆樹的效率往往就是噩夢.
ACM中解決樹的問題往往是這樣的: 根據實際問題抽象出樹的模型(這樣的模型往往是多樣的),這就是一個繁的過程,然後找出樹的重複結點(一棵很高的樹往往有很多重複的結點),隨即在遍曆中忽視這些重複結點從而提高效率.
ACM樹的效率方式往往是這樣的: 遞迴=遞迴+最高效率
北大的網站上有一道簡單的ACM題目就是用樹來解決問題:
http://acm.pku.edu.cn/JudgeOnline/showproblem?problem_id=1088
下面是我的C++代碼:
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std; //使用標準庫函數
int temp[100][100];
int R,C;
int point[100][100];
int i=0,j=0;
int around(int m,int n,int k,int s){//判斷該點是否比起始點"低"
if(point[m][n]<point[k][s]){
return 1;
}
else return 0;
}
int look(int m,int n){
int max=0;
int a=0,b=0,c=0,d=0;
if(temp[m][n]!=0){ return temp[m][n]; }//如果該點算過了,就不要在計算,提高效率
if(m+1<R) if(around(m+1,n,m,n)==1){a=look(m+1,n)+1; }//遍曆該點周圍的四個點
if(m-1>=0) if(around(m-1,n,m,n)==1) {b=look(m-1,n)+1;}
if(n+1<C) if(around(m,n+1,m,n)==1) {c=look(m,n+1)+1; }
if(n-1>=0) if(around(m,n-1,m,n)==1) {d=look(m,n-1)+1; }
max=a;
if(b>=max) max=b;
if(c>=max) max=c;
if(d>=max) max=d;
return max;
}
int main(){
int ss=0;
cin>>R>>C;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
cin>>point[i][j];
}
}
for(i=0;i<R;i++){
for(j=0;j<C;j++){
temp[i][j]=look(i,j);
if(ss<temp[i][j]) ss=temp[i][j];
}
}
ss=ss+1;//沒有算最低點高度, 加一個1補上
cout<<ss<<endl;
}
這個演算法在北大上測試時間為93ms 通過了它的時間效率測試. 當然肯定有比它更好的演算法,我的這個只是一種普通思路,對我們這些凡人來說是很好學的,何樂而不為呢?