算法竞赛入门经典(第二版) 答案汇总(持续更新)
大佬們,更不動了啊,真的沒時間啊
第二章
習題2-1 水仙花數( daffodil)
輸出
?
輸出100~ 999中的所有水仙花數。 若3位數ABC滿足ABC= A3+ B3+ C3, 則稱其為水仙花
數。 例如153= 13+ 53+ 33, 所以153是水仙花數。
?
?
# include <iostream>using namespace std;int main(){int ABC = 100;for( ; ABC <= 999; ABC++){int A3, B3, C3;A3 = ABC / 100; B3 = ABC / 10 % 10; C3 = ABC % 10;if(ABC == A3*A3*A3 + B3*B3*B3 + C3*C3*C3)cout << ABC << ' ' ;}cout << endl;return 0; }?
?
?
習題2-2 韓信點兵( hanxin)
相傳韓信才智過人, 從不直接清點自己軍隊的人數, 只要讓士兵先后以三人一排、 五人
一排、 七人一排地變換隊形, 而他每次只掠一眼隊伍的排尾就知道總人數了。 輸入包含多組
數據, 每組數據包含3個非負整數a, b, c, 表示每種隊形排尾的人數( a< 3, b< 5, c<
7) , 輸出總人數的最小值( 或報告無解) 。 已知總人數不小于10, 不超過100。 輸入到文件
結束為止。
# include <iostream> # define LOCAL using namespace std;int main(){ /* # ifdef LOCALfreopen("C:\\Users\\Administrator\\Desktop\\新建文本文檔.txt", "r", stdin);freopen("C:\\Users\\Administrator\\Desktop\\新建文本文檔2.txt", "w", stdout);# endif */int a, b, c, flag = 0, count = 0;while(cin >> a >> b >> c){count++;flag = 0;for(int i = 0; i < 34; i++){int num = 3 * i + a;if(num % 5 == b && num % 7 == c && num >0 && num < 100){cout << "Case " << count << ": " << num << endl;flag = 1;}}if(!flag)cout << "Case " << count << ": " << "NO answer!" << endl;} }?
習題2-3 倒三角形( triangle)
輸入正整數n≤20, 輸出一個n層的倒三角形。 例如, n= 5時輸出如下:
#########
#######
#####
###
?
#
# include <iostream> using namespace std;int main(){int n, k;cin >> n;k = 2*n-1;for(int i = 0; i < n; i++){for(int j = i; j > 0; j--){cout << ' ';}for( ; k > 0; k--){cout << "*";}k = 2*n-1 - (i+1)*2;cout << endl;} return 0; }?
?
?
題2-4 子序列的和( subsequence)
輸入兩個正整數n< m< 106, 輸出 , 保留5位小數。 輸入包含多組數據,
結束標記為n= m= 0。 提示: 本題有陷阱。?
?
?
?
習題2-5 分數化小數( decimal)
輸入正整數a, b, c, 輸出a/b的小數形式, 精確到小數點后c位。 a, b≤106, c≤100。 輸
入包含多組數據, 結束標記為a= b= c= 0。?
?
?
?
習題2-6 排列( permutation)
用1, 2, 3, …, 9組成3個三位數abc, def和ghi, 每個數字恰好使用一次, 要
求abc: def: ghi= 1: 2: 3。 按照“abc def ghi”的格式輸出所有解, 每行一個解。 提示: 不必太動腦筋。
?
?
?
課后思考題2。 下面的程序運行結果是什么? “! = ”運算符表示“不相等”。 提示: 請上機實
驗, 不要憑主觀感覺回答。
?
第三章
?
3-12 處的例子(很有意思,個人推薦試一下)
//輸出流的問題
# include <iostream> using namespace std;int main(){int count = 1;count = count++;cout << count << endl; cout << count++ << ',' << count++ << ',' << count++ << endl; }?
習題3-1 得分( Score, ACM/ICPC Seoul 2005, UVa1585)
給出一個由O和X組成的串( 長度為1~ 80) , 統計得分。 每個O的得分為目前連續出現
?
的O的個數, X的得分為0。 例如, OOXXOXXOOO的得分為1+2+0+0+1+0+0+1+2+3。
# include <iostream> using namespace std;int main(){char s[100001], ch = 1;int n = 0;scanf("%d", &n);while(n--){int flag = 0, i = 0, score = 0;scanf("%s", s);while(s[i] != '\0'){if(s[i++] == 'O') score += ++flag;else flag = 0;}cout << score << endl;}return 0; }?
習題3-2 分子量( Molar Mass, ACM/ICPC Seoul 2007, UVa1586)
給出一種物質的分子式( 不帶括號) , 求分子量。 本題中的分子式只包含
?
給出一種物質的分子式( 不帶括號) , 求分子量。 本題中的分子式只包含4種原子, 分
別為C, H, O, N, 原子量分別為12.01, 1.008, 16.00, 14.01( 單位: g/mol) 。 例如, C6H5OH的
?
分子量為94.108g/mol。
# include <iostream> # include <cstring> using namespace std;int main(){const double C = 12.01, H = 1.008, O = 16.00, N = 14.01;int n; scanf("%d", &n);while(n--){double sum_w = 0;char s[10000];scanf("%s", s);for(int i = 0; i < strlen(s); ){int num = 0, j = i + 1, k = i;if(s[j] - '0' < 9 && s[j] != '\0'){num = s[j] - '0', j++;for( ; s[j] - '0' < 9 && s[j] != '\0'; j++)num = num * 10 + (s[j] - '0');i = j;}else num = 1, i++;switch (s[k]){case 'C': sum_w += 12.01 * num; break;case 'H': sum_w += 1.008 * num; break;case 'O': sum_w += 16.00 * num; break;case 'N': sum_w += 14.01 * num; break; }}printf("%.3lf\n", sum_w);}return 0; }
習題3-3 數數字( Digit Counting , ACM/ICPC Danang 2007, UVa1225)
把前n( n≤10000) 個整數順次寫在一起: 123456789101112…數一數0~ 9各出現多少次
?
( 輸出10個整數, 分別是0, 1, …, 9出現的次數) 。
?
# include <iostream> # include <cstring> using namespace std;int main(){int n, a; cin >> n;while(n--){int s[10];memset(s, 0, sizeof(s));cin >> a;for(int i = 1; i <= a; i++){int j = 0, k = i;while(1){int a1 = k % 10;s[a1]++, k /= 10;if(k / 10 == 0 && k % 10 == 0)break;}}for(int i = 0; i < 9; i++)cout << s[i] << ' ';cout << s[9] << endl;}return 0; }
習題3-4 周期串( Periodic Strings, UVa455)
如果一個字符串可以由某個長度為k的字符串重復多次得到, 則稱該串以k為周期。 例
如, abcabcabcabc以3為周期( 注意, 它也以6和12為周期) 。
?
輸入一個長度不超過80的字符串, 輸出其最小周期。
?
? # include <iostream> # include <cstring> using namespace std;int main(){int n;scanf("%d", &n);while(n--){char s[100];scanf("%s", s);int flag = 0;for(int min_len = 1; min_len <= strlen(s); min_len++){if(strlen(s) % min_len != 0) continue;for(int i = 0; i < strlen(s); i++){if(s[i % min_len] != s[i])break;else if(i == strlen(s) - 1){flag = 1;if(n) cout << min_len << endl << endl;else cout << min_len << endl;}}if(flag) break;}} return 0; }?
?
習題3-5 謎題( Puzzle, ACM/ICPC World Finals 1993, UVa227)
有一個5*5的網格, 其中恰好有一個格子是空的, 其他格子各有一個字母。 一共有4種指
令: A, B, L, R, 分別表示把空格上、 下、 左、 右的相鄰字母移到空格中。 輸入初始網格和指
令序列( 以數字0結束) , 輸出指令執行完畢后的網格。 如果有非法指令, 應輸出“This
?
?
puzzle has no final configuration.”, 例如, 圖3-5中執行ARRBBL0后, 效果如圖3-6所示
# include <iostream> # include <cstring> using namespace std;int main(){ // freopen("C:\\1.txt", "r", stdin);int n = 1, c = 0; while(n++){int flag = 0;// flag 進行輸出判斷 char s[10][10], s1[100];int x = 0, y = 0, index_x, index_y; // 空格的坐標 for(int i = 0; i < 5; i++){ fgets(s[i], 100, stdin);if(s[0][0] == 'Z') return 0;} for(int i = 0; i < 5; i++) // 找空格位置 for(int j = 0; j < 5; j++){if(s[i][j] < 'A' || s[i][j] > 'Z'){x = i, y = j;index_x = x, index_y = y;break;}}int j = 0;while((s1[j++] = getchar()) != '0'){} // 讀取移動指令 getchar(); j = 0; // 這個getchar() 一定要有,坑了我好久!!! while(s1[j++] != '0'){ // 執行移動指令switch(s1[j-1]){case 'A':index_x--; break;case 'B':index_x++; break;case 'L':index_y--; break;case 'R':index_y++; break;}if(index_x < 0 || index_x > 4 || index_y < 0 || index_y > 4){flag = 1; break;}else{s[x][y] = s[index_x][index_y];s[index_x][index_y] = ' ';x = index_x, y = index_y;}}if(c++) cout << endl;cout << "Puzzle #" << n - 1 << ':' << endl;if(flag) {cout << "This puzzle has no final configuration." << endl;continue; }for(int i = 0; i < 5; i++){for(int j = 0; j < 5; j++){if(j) cout << ' ';cout << s[i][j];}cout << endl;}}return 0; }?
?
?
?
習題3-6 縱橫字謎的答案( Crossword Answers, ACM/ICPC World Finals 1994,
UVa232)
輸入一個r行c列( 1≤r, c≤10) 的網格, 黑格用“*”表示, 每個白格都填有一個字母。 如
果一個白格的左邊相鄰位置或者上邊相鄰位置沒有白格( 可能是黑格, 也可能出了網格邊
界) , 則稱這個白格是一個起始格。
首先把所有起始格按照從上到下、 從左到右的順序編號為1, 2, 3,…, 如圖3-7所示?
?
?
?
習題4-1 象棋( Xiangqi, ACM/ICPC Fuzhou 2011, UVa1589)
考慮一個象棋殘局, 其中紅方有n( 2≤n≤7) 個棋子, 黑方只有一個將。 紅方除了有一個
帥( G) 之外還有3種可能的棋子: 車( R) , 馬( H) , 炮( C) , 并且需要考慮“蹩馬
腿”( 如圖4-4所示) 與將和帥不能照面( 將、 帥如果同在一條直線上, 中間又不隔著任何棋
子的情況下, 走子的一方獲勝) 的規則。
輸入所有棋子的位置, 保證局面合法并且紅方已經將軍。 你的任務是判斷紅方是否已經
?
把黑方將死。 關于中國象棋的相關規則請參見原題。
# include <iostream> # include <cstring> # include <cmath> using namespace std;struct pst{char ch;int x;int y; }; bool is_alive(int flag[][11], int x, int y){ // 只有 0 才可以走 for(int i = 1; i < 4; i++){for(int j = 4; j < 7; j++){ // 這樣的好處是可以避免 越界 if(abs(x - i) == 1 && y == j && !flag[i][j]) // 短路求值 return false;else if(abs(y - j) == 1 && x == i && !flag[i][j]) // 短路求值 return false;}}return true; }void Gernal(int flag[][11], int x, int y){ // 紅將軍 可以打得范圍 // cout << "GGGG" << endl;for(int i = x-1; i > 0; i--){if(flag[i][y] == 999)break;else{flag[i][y] = 1; // cout << i << endl;} } }void Chariot(int flag[][11], int x, int y){ // 車可以打得范圍 // cout << "RRRRRRRR" << endl;for(int i = 0; i < 11; i++){if(flag[i][y] == 999) break;else flag[i][y] = 1; // cout << i << endl;if(i == x - 1) i++;}for(int j = 0; j < 11; j++){if(flag[x][j] == 999) break;else flag[j][y] = 1; // cout << j << endl;if(j == y - 1) j++;} }void Cannon(int flag[][11], int x, int y){ // 炮可以打得范圍 // cout << "CCCCCCC" << endl; for(int i = x+1; i < 11; i++){if(flag[i][y] == 999 && i != 10){for(int k = i+1; k < 11 && flag[k][y] != 999; k++){flag[k][y] = 1; // cout << k << endl; }break;}} // cout << endl;for(int i = x-1; i > 0; i--){if(flag[i][y] == 999 && i != 1){for(int k = i-1; k > 0 && flag[k][y] != 999; k--){flag[k][y] = 1; // cout << k << endl; }}} // cout << endl;for(int j = y+1; j < 11; j++){if(flag[x][j] == 999 && j != 10){for(int k = j+1; k < 11 && flag[x][k] != 999; k++){flag[x][k] = 1; // cout << k << endl; }break;}} // cout << endl;for(int j = y-1; j > 0; j--){if(flag[x][j] == 999 && j != 1){for(int k = j-1; k > 0 || flag[x][k] != 999; k--){flag[x][k] = 1; // cout << k << endl; }}} // cout << endl; }void Horse(int flag[][11], int x, int y){ // 馬可以打的范圍 // cout << "HHHHHH" << endl; if(flag[x + 1][y] != 999){flag[x + 2][y + 1] = 1;flag[x + 2][y - 1] = 1;}if(flag[x - 1][y] != 999){flag[x - 2][y + 1] = 1;flag[x - 2][y - 1] = 1; } if(flag[x][y + 1] != 999){flag[x + 1][y + 2] = 1;flag[x - 1][y + 2] = 1;}if(flag[x][y - 1] != 999){flag[x + 1][y - 2] = 1;flag[x - 1][y - 2] = 1;} }int main(){freopen("C:\\1.txt", "r", stdin);int N, bg_x, bg_y, flag[11][11];memset(flag, 0, sizeof(flag));pst red[100];while(1){cin >> N >> bg_x >> bg_y;if(!N) break;for(int i = 0; i < N; i++){ // 輸入,并標記 棋子 為max cin >> red[i].ch >> red[i].x >> red[i].y;// cout << red[i].ch << red[i].x << red[i].y << endl;flag[red[i].x][red[i].y] = 999;}for(int i = 0; i < N; i++){ // 逐個壓縮黑方將軍空間 可以打得地方標記為 1 switch(red[i].ch){case 'G':Gernal(flag, red[i].x, red[i].y);break;case 'R':Chariot(flag, red[i].x, red[i].y);break;case 'C':Cannon(flag, red[i].x, red[i].y);break;case 'H':Horse(flag, red[i].x, red[i].y);break;}}if(is_alive(flag, bg_x, bg_y))cout << "Yes" << endl;elsecout << "No" << endl;} return 0; }?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的算法竞赛入门经典(第二版) 答案汇总(持续更新)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【R】语言第五课----画图
- 下一篇: iOS 蓝牙开发中数据收发的坑