算法在計算機領域有着十分重要的地位,不僅具有深遠的理論意義,而且解決了許多實際的問題,提高了程序執行效率。由此催生了一系列以算法為核心的競賽,意在豐富和創造運用計算機解決實際問題的能力。隨着各類算法競賽的快速發展,規模也逐步擴大,受到了全世界范圍內各高校、互聯網公司和相關單位的認可和重視。
目前比較火熱和主流的算法競賽有ACM國際大學生程序設計競賽(ACM International Collegiate Programming Contest,簡稱ACM-ICPC或ICPC)和中國大學生程序設計競賽(China Collegiate Programming Contest, 簡稱CCPC)。他們以團隊的形式代表各學校參賽,每隊由至多3名隊員組成。比賽期間,每隊使用1台電腦需要在5個小時內使用C、C++、Pascal或Java中的一種編寫程序解決7到13個問題。程序完成之后提交裁判運行,運行的結果會判定為正確或錯誤兩種並及時通知參賽隊。而且有趣的是每隊在正確完成一題后,組織者將在其位置上升起一只代表該題顏色的氣球,每道題目第一支解決掉它的隊還會額外獲得一個FIRST PROBLEM SOLVED
的氣球。
第1關:程序三步曲
任務描述
本關任務:編寫一個程序實現兩個整數a
和b
的大小比較,並完成數據讀取、運算分析和輸出結果三步曲。
相關知識
為了完成本關任務,你需要掌握:1.數據讀取,2.運算分析,3.輸出結果。
數據讀取
C語言常用的讀取函數是scanf
,它是格式輸入函數,被聲明在頭文件stdio.h
里,因此在使用scanf
函數時要加上#include <stdio.h>
。 函數原型:
1 int scanf(const char * restrict format,...); 2 // format表示輸入指令格式
例如讀取兩個整數 a
和 b
:
1 int a, b; 2 scanf("%d %d", &a, &b);
C++程序設計語言常用的讀取函數是cin
,使用提取運算符 >>
,讀取數據格式多樣,使用cin
時要加上#include <iostream.h>
(新版本編譯器為#include <iostream>
)。 例如:
1 int a; 2 float b; 3 char c; 4 cin>>a>>b>>c;
在算法競賽中,程序I/O
的時間開銷是非常關鍵的,scanf
因其格式化輸入與cin
相比只需要很小的時間開銷,更為常用。
運算分析
運算分析是算法競賽中的重中之重,它決定了該問題選取什么算法,做出什么改進,最終得出什么結論。 計算機程序語言中變量的比較實際上是ASCII碼
的比較,例如a=0
,b=1
,他們的ASCII碼
值分別是48
和49
,因此0<1
符合ASCII值48<49
。
輸出結果
printf
函數是格式化輸出函數,調用格式為: printf("<格式化字符串>", <參量表>)
,與scanf
一樣被定義在被聲明在頭文件stdio.h
里。
函數原型:
1 extern int printf(const char *format,...);
另外,cout
函數是C++編程語言互換流中的標准輸出流,需要iostream
支持。 在算法競賽中,printf
格式化輸出函數對程序結果的指定輸出來說是非常方便實用的。
編程要求
本關的編程任務是補全右側代碼片段main
中Begin
至End
中間的代碼,具體要求如下:
- 在
mian
中,完成兩個整數a
和b
的讀取,並且比較他們的大小,最后輸出這兩個整數的升序序列。
測試說明
平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。
以下是平台的測試樣例:
測試輸入:2 1
預期輸出:1 2
輸入格式:兩個整數 a
和b
輸出格式:輸出兩個整數的升序,中間空格隔開,末尾換行。
Tips:競賽中采用黑盒測試的方式對輸出結果進行驗證,因此輸出結果的格式是異常嚴格的。

1 // 2 // main.cpp 3 // step1 4 // 5 // Created by ljpc on 2018/6/20. 6 // Copyright © 2018年 ljpc. All rights reserved. 7 // 8 9 #include <iostream> 10 11 int main(int argc, const char * argv[]) { 12 13 // 請在這里補充代碼,完成本關任務 14 /********** Begin *********/ 15 int a,b; 16 scanf("%d %d",&a,&b); 17 if(a>b) printf("%d %d",b,a); 18 else printf("%d %d",a,b); 19 20 /********** End **********/ 21 22 return 0; 23 }
第2關:牛刀小試
任務描述
本關任務:編寫一個程序實現三個整數a
,b
和c
的大小比較,並完成數據讀取、運算分析和輸出結果三步曲。
相關知識
為了完成本關任務,你需要掌握:1.三個數比較。
三個數比較
三個數a
,b
,c
的比較方法比兩個數的比較方法稍微復雜一點,但仍然是簡單的,例如以下兩種思路:
- 三個數共
3x2x1
六種排列,暴力判斷a<b && b<c
至c<b && b<a
六種排列。 - 先判斷一個最小值
a<b && a<c
,若滿足再判斷b<c
還是c<b
。
編程要求
本關的編程任務是補全右側代碼片段main
中Begin
至End
中間的代碼,具體要求如下:
- 在
main
中,完成三個整數a
,b
和c
的讀取,並且比較他們的大小,最后輸出這三個整數的升序序列。
測試說明
平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。
以下是平台的測試樣例:
測試輸入:3
2
1
預期輸出:1
2
3
輸入格式:三個整數a
,b
,c
。
輸出格式:輸出三個整數的升序,中間空格隔開,末尾換行。
開始你的任務吧,祝你成功!

1 // 2 // main.cpp 3 // step2 4 // 5 // Created by ljpc on 2018/6/20. 6 // Copyright © 2018年 ljpc. All rights reserved. 7 // 8 9 #include <iostream> 10 11 int main(int argc, const char * argv[]) { 12 13 // 請在這里補充代碼,完成本關任務 14 /********** Begin *********/ 15 int a,b,c; 16 scanf("%d %d %d",&a,&b,&c); 17 if(a>b&&b>c) printf("%d %d %d",c,b,a); 18 if(a>c&&c>b) printf("%d %d %d",b,c,a); 19 if(b>c&&c>a) printf("%d %d %d",a,c,b); 20 if(b>a&&a>c) printf("%d %d %d",c,a,b); 21 if(c>b&&b>a) printf("%d %d %d",a,b,c); 22 if(c>a&&a>b) printf("%d %d %d",b,a,c); 23 /********** End **********/ 24 25 return 0; 26 }
第3關:嶄露頭角
任務描述
本關任務:編寫一個程序實現n
個整數的大小比較,輸出升序序列,並完成數據讀取、運算分析和輸出結果三步曲。
相關知識
為了完成本關任務,你需要掌握:1.數列排序。
數列排序
在算法競賽中,往往根據數據的規模而設計相應的算法來求解問題。前兩個關卡的數據規模非常小,少量的代碼就能完成程序的實現。但本關卡的數據規模為n
,將有n!
種排列,難以枚舉。因此需要設計針對n
個整數的排序算法,例如冒泡排序。
冒泡排序重復地遍歷待排序的數列,每次比較兩個相鄰元素,如果它們的順序錯誤就把它們交換。重復地進行遍歷直到沒有再需要交換時表示數列已經排序完成。
-
算法步驟:
-
比較相鄰的元素:若第一個比第二個大,則交換;
-
遍歷開始第一對到結尾最后一對,執行步驟
1
; -
重復步驟
1
~2
,直到排序完成。
-
-
可改進的冒泡排序:第一趟排序之后最后一個元素是最大的,因此下一趟遍歷只需執行到倒數第二對。
編程要求
本關的編程任務是補全右側代碼片段main
中Begin
至End
中間的代碼,具體要求如下:
- 在
main
中,完成n
個整數的讀取,並且比較他們的大小,最后輸出這n
個整數的升序序列。
測試說明
平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。
以下是平台的測試樣例:
測試輸入: 10
9 8 7 6 5 4 3 2 1 0
預期輸出: 0 1 2 3 4 5 6 7 8 9
輸入格式:第一行整數n
,第二行n
個整數。
輸出格式:n
個整數,中間空格隔開,末尾換行。
開始你的任務吧,祝你成功!
Tips:更多的排序算法請參考實訓《數據結構-十大經典排序算法》 https://www.educoder.net/shixuns/r5xsukn4/challenges

1 // 2 // main.cpp 3 // step3 4 // 5 // Created by ljpc on 2018/6/20. 6 // Copyright ? 2018年 ljpc. All rights reserved. 7 // 8 9 #include <iostream> 10 int a[100001]; 11 int main(int argc, const char * argv[]) { 12 13 // 請在這里補充代碼,完成本關任務 14 /********** Begin *********/ 15 int t,c; 16 scanf("%d",&t); 17 for(int i=1;i<=t;i++){ 18 scanf("%d",&a[i]); 19 } 20 for(int i=1;i<=t;i++) 21 for(int j=1;j<=t-1;j++){ 22 if(a[j]>a[j+1]){ 23 c=a[j]; 24 a[j]=a[j+1]; 25 a[j+1]=c; 26 } 27 else continue; 28 } 29 for(int i=1;i<=t;i++) 30 printf("%d ",a[i]); 31 /********** End **********/ 32 return 0; 33 }
第4關:結構體運
任務描述
本關任務:給定矩形的某一對角線坐標,編寫一個程序運用結構體完成矩形中心點、面積和周長的計算。
相關知識
為了完成本關任務,你需要掌握:1.結構體,2.矩形相關概念。
結構體
C++
中除了支持結構體struct
之外,還支持類class
,由此C++
的結構體除了可以有變量(稱之為成員變量)外,還可以有函數(稱之為成員函數)。算法競賽中因為時間緊張,通常使用結構體來替代類,提升編程效率,而工程中則是將結構體作為純數據類型,僅僅包含少量的輔助成員函數。C++
中類的成員變量,成員函數,構造函數都可以在C++
結構體中得以實現。
例如定義一個二維坐標軸中的點結構體Point
,包含兩個成員變量:橫坐標x
和縱坐標y
,以及一些成員函數和重載函數:
1 struct Point{ 2 double x, y; 3 Point(){x=y=0;}// 重載初始化函數 4 Point(double x_, double y_):x(x_), y(y_){} 5 void in(){scanf("%lf %lf", &x, &y);}// 讀入數據函數 6 void out(){printf("%.2lf %.2lf\n", x, y);}// 輸出數據函數 7 Point operator + (Point P){// 重載 + 操作 8 Point Q; 9 Q.x = x + P.x; 10 Q.y = y + P.y; 11 return Q; 12 } 13 }; 14 Point P1; // 定義一個點 P1 15 Point P2 = Point(1, 1); // 定義一個點 P2
矩形相關概念
- 矩形中心點:對角線的交點
- 矩形面積:矩形長乘以寬的結果
- 矩形周長:矩形四條邊的長度和
編程要求
本關的編程任務是補全右側代碼片段area
,perimeter
和center
中Begin
至End
中間的代碼,具體要求如下:
- 在
area
中,利用結構體的相關操作完成矩形面積的計算。 - 在
perimeter
中,利用結構體的相關操作完成矩形周長的計算。 - 在
center
中,利用結構體的相關操作完成矩形中心點的計算。
測試說明
平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。
以下是平台的測試樣例:
測試輸入:
0 0
2 2
預期輸出:
中心點 1.00 1.00
面積 4.00
周長 8.00
輸入格式:矩形對角線上的兩點在二維坐標軸的位置坐標
輸出格式:輸出結果保留小數點后兩位,中間空格隔開,末尾換行。
開始你的任務吧,祝你成功!

1 // 2 // main.cpp 3 // step4 4 // 5 // Created by ljpc on 2018/6/20. 6 // Copyright © 2018年 ljpc. All rights reserved. 7 // 8 9 #include <iostream> 10 #include <math.h> 11 struct Point{ 12 double x, y; 13 // 重載初始化函數 14 Point(){x=y=0;} 15 Point(double x_, double y_):x(x_), y(y_){} 16 17 // 讀入數據函數 18 void in(){scanf("%lf %lf", &x, &y);} 19 20 // 輸出數據函數 21 void out(){printf("%.2lf %.2lf\n", x, y);} 22 23 // 重載 + 操作 24 Point operator + (Point P){ 25 Point Q; 26 Q.x = x + P.x; 27 Q.y = y + P.y; 28 return Q; 29 } 30 31 // 重載 - 操作 32 Point operator - (Point P){ 33 Point Q = Point(0, 0); 34 Q.x = x - P.x; 35 Q.y = y - P.y; 36 return Q; 37 } 38 39 // 重載 * 操作 40 Point operator * (double scale){ 41 Point Q = Point(0, 0); 42 Q.x = x * scale; 43 Q.y = y * scale; 44 return Q; 45 } 46 47 }; 48 49 // 計算面積 50 double area(Point p1, Point p2) 51 // 參數:矩形對角線上的兩點p1(x1, y1), p2(x2, y2) 52 // 返回:矩形面積 53 { 54 // 請在這里補充代碼,完成本關任務 55 /********** Begin *********/ 56 return abs((p1.x-p2.x)*(p1.y-p2.y)); 57 58 /********** End **********/ 59 } 60 61 // 計算周長 62 double perimeter(Point p1, Point p2) 63 // 參數:矩形對角線上的兩點p1(x1, y1), p2(x2, y2) 64 // 返回:矩形周長 65 { 66 // 請在這里補充代碼,完成本關任務 67 /********** Begin *********/ 68 return (abs(p1.x-p2.x)+abs(p1.y-p2.y))*2; 69 70 /********** End **********/ 71 } 72 73 // 計算中心點 74 Point center(Point p1, Point p2) 75 // 參數:矩形對角線上的兩點p1(x1, y1), p2(x2, y2) 76 // 返回:矩形中心點 77 { 78 // 請在這里補充代碼,完成本關任務 79 /********** Begin *********/ 80 Point Q = Point(0,0); 81 Q.x=(p1.x+p2.x)*0.5; 82 Q.y=(p1.y+p2.y)*0.5; 83 return Q; 84 /********** End **********/ 85 } 86 87 int main(int argc, const char * argv[]) { 88 89 90 // 1.讀取數據 91 Point p1, p2; 92 p1.in(); 93 p2.in(); 94 95 // 2.運算分析 96 Point pc = center(p1, p2); 97 double s = area(p1, p2); 98 double c = perimeter(p1, p2); 99 100 // 3.輸出結果 101 printf("中心點 "); 102 pc.out(); 103 104 printf("面積 %.2lf\n", s); 105 106 printf("周長 %.2lf\n", c); 107 108 109 return 0; 110 }