# 演算法課程題解 - 巢狀迴圈 # TOJ 104 ## 題目 https://toj.tfcis.org/oj/pro/104/ 輸入一個正整數 $n$ ,輸出高度為 $n$ 的星星樹 ## 解法 By Koios1143 ### 想法 第一次接觸星星樹這類的題目可以藉由觀察來寫下迴圈 我們可以先把星星樹的每一層給一個數字 以下考慮 $n=4$ 的情況 ``` 0 | * 1 | *** 2 | ***** 3 |******* ``` 接下來觀察每一行內空格和數字的關係 ``` 第 0 行 有 3 個空格 第 1 行 有 2 個空格 第 2 行 有 1 個空格 第 3 行 有 0 個空格 ``` 因為空個的數量與 $n$ 息息相關,我們換成與 $n$ 相關的話來看看 ``` 第 0 行 有 n-1 個空格 第 1 行 有 n-2 個空格 第 2 行 有 n-3 個空格 第 3 行 有 n-4 個空格 ``` 再加上與行數的關係 ``` 第 0 行 有 (n-1)-0 個空格 第 1 行 有 (n-1)-1 個空格 第 2 行 有 (n-1)-2 個空格 第 3 行 有 (n-1)-3 個空格 ``` 發現到關係了嗎? 那麼我們也考慮星星的情況 ``` 第 0 行 有 1 個星星 第 1 行 有 3 個星星 第 2 行 有 5 個星星 第 3 行 有 7 個星星 ``` 星星的數量無論 $n$ 是多少,順序仍然相同,都是從 $1$ 開始,並且每次加上 $2$ ,所以接下來直接考慮與行數的關係 ``` 第 0 行 有 (0+1)*2-1 個星星 第 1 行 有 (1+1)*2-1 個星星 第 2 行 有 (2+1)*2-1 個星星 第 3 行 有 (3+1)*2-1 個星星 ``` 有了這些關係式,我們就可以輕易地寫出巢狀迴圈了 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> using namespace std; int main() { int n; cin>>n; // i 表示行數 for(int i=0 ; i<n ; i++){ // 先輸出空格 for(int j=0 ; j<n-1-i ; j++){ cout<<' '; } // 再輸出星星 for(int j=0 ; j<2*(i+1)-1 ; j++){ cout<<'*'; } cout<<'\n'; } return 0; } ``` ### 複雜度分析 總時間複雜度約為 $O(n^2)$ # TOJ 110 ## 題目 https://toj.tfcis.org/oj/pro/110/ 第一行有一個正整數數 $n$,接下來有 $n$ 行,每行有一個數,表示三角形的高度 請依照題目的樣子輸出六芒星 例如 $n = 4$ 時輸出 ``` * ******* ***** ******* * ``` $n = 5$ 時輸出 ``` * *** ********* ******* ********* *** * ``` ## 解法 By Koios1143 ### 想法 把六芒星拆成上面的三角形、中間三個橫線、下面的三角形來輸出 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> using namespace std; int main(){ int n,m; cin>>n; while(n--){ cin>>m; // 上面星星樹樹 // i 表示行數 for(int i=0 ; i<m-3 ; i++){ // 先輸出空白 for(int j=0 ; j<m-1-i ; j++){ cout<<' '; } // 再輸出星星 for(int j=0 ; j<(i+1)*2-1 ; j++){ cout<<'*'; } cout<<'\n'; } // 中間三條線 for(int i=0 ; i<2*m-1 ; i++){ cout<<'*'; } cout<<"\n "; for(int i=0 ; i<2*m-3 ; i++){ cout<<'*'; } cout<<"\n"; for(int i=0 ; i<2*m-1 ; i++){ cout<<'*'; } cout<<'\n'; // 下面星星樹 // i 表示行數 for(int i=0 ; i<m-3 ; i++){ // 先輸出空白 for(int j=0 ; j<3+i ; j++){ cout<<' '; } // 再輸出星星 for(int j=0 ; j<(m-3)*2-1-2*i ; j++){ cout<<'*'; } cout<<'\n'; } } return 0; } ``` ### 複雜度分析 總時間複雜度約為 $O(n(2m^2 + 3m))$ 約為 $O(nm^2)$ # UVa 382 ## 題目 http://domen111.github.io/UVa-Easy-Viewer/?382 給很多個數字 $n$ ,對於每個 $n$ ,求該數字的所有因數,不包含自己本身的總和 如果等於輸出 `PERFECT` ,若小於輸出 `DEFICIENT` ,若大於輸出 `ABUNDANT` ## 解法 By Koios1143 ### 想法 對於每個 $n$ 暴力掃過一遍看看有那些因數,加總起來判斷 至於輸出要對齊的部分,這邊採用 log 的方式得知求出的數字是幾位數,進而判斷出應該要填充多少的空格 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> #include<cmath> using namespace std; int n, cnt=0; int main(){ cout<<"PERFECTION OUTPUT\n"; while(cin>>n && n){ cnt=0; for(int i=1 ; i<n ; i++){ if(n%i==0){ cnt+=i; } } for(int i=0, p=5-((int)log10(n)+1) ; i<p ; i++){ cout<<' '; } cout<<n<<" "; if(cnt==n){ cout<<"PERFECT\n"; } else if(cnt<n){ cout<<"DEFICIENT\n"; } else{ cout<<"ABUNDANT\n"; } } cout<<"END OF OUTPUT\n"; return 0; } ``` ### 複雜度分析 每筆測試資料時間複雜度為 $O(n)$ # UVa 488 ## 題目 http://domen111.github.io/UVa-Easy-Viewer/?488 輸入兩個整數 $a, f$ 表示三角形波的振幅以及頻率,請輸出該三角波 ## 解法 By Koios1143 輸出格式要多加留意 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> using namespace std; int t,f,a; bool out=false; int main(){ cin>>t; while(t--){ if(out) cout<<"\n"; else out=true; cin>>a>>f; for(int i=0 ; i<f ; i++){ if(i!=0) cout<<"\n"; // 上大三角 for(int j=1 ; j<=a ; j++){ for(int k=1 ; k<=j ; k++){ cout<<j; } cout<<'\n'; } // 下小三角 for(int j=a-1,l=0 ; j>=1 ; j--, l++){ for(int k=a-1-l ; k>0 ; k--){ cout<<j; } cout<<"\n"; } } } return 0; } ``` ### 複雜度分析 每筆測試資料時間複雜度約為 $O(2f(a^2))$ 總時間複雜度約為 $O(2tf(a^2))$ # UVa 11074 ## 題目 http://domen111.github.io/UVa-Easy-Viewer/?11074 依照題目需求輸出圖形 ## 解法 By Koios1143 ### 程式碼 ```cpp= //By Koios1143 #include<iostream> using namespace std; int main(){ int s,t,n,l,Case=1; while(cin>>s>>t>>n && (s!=0 && t!=0 && n!=0)){ cout<<"Case "<<Case++<<":\n"; l=s*n+t*(n+1); for(int k=0 ; k<n ; k++){ for(int i=0 ; i<t ; i++){ for(int j=0 ; j<l ; j++){ cout<<'*'; } cout<<"\n"; } for(int i=0 ; i<s ; i++){ for(int j=0 ; j<n ; j++){ for(int p=0 ; p<t ; p++){ cout<<'*'; } for(int p=0 ; p<s ; p++){ cout<<'.'; } } for(int j=0 ; j<t ; j++){ cout<<'*'; } cout<<"\n"; } } for(int i=0 ; i<t ; i++){ for(int j=0 ; j<l ; j++){ cout<<'*'; } cout<<"\n"; } cout<<"\n"; } return 0; } ``` ### 複雜度分析 每筆測試資料時間複雜度為 $O((s*n+t*(n+1))^2)$ ###### tags: `SCIST 演算法 題解`