頭歌 | 數據結構與算法課程設計-算法與競賽(第1章) - 入門指南


算法在計算機領域有着十分重要的地位,不僅具有深遠的理論意義,而且解決了許多實際的問題,提高了程序執行效率。由此催生了一系列以算法為核心的競賽,意在豐富和創造運用計算機解決實際問題的能力。隨着各類算法競賽的快速發展,規模也逐步擴大,受到了全世界范圍內各高校、互聯網公司和相關單位的認可和重視。

目前比較火熱和主流的算法競賽有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關:程序三步曲

任務描述

本關任務:編寫一個程序實現兩個整數ab的大小比較,並完成數據讀取、運算分析和輸出結果三步曲。

相關知識

為了完成本關任務,你需要掌握:1.數據讀取,2.運算分析,3.輸出結果。

數據讀取

C語言常用的讀取函數是scanf,它是格式輸入函數,被聲明在頭文件stdio.h里,因此在使用scanf函數時要加上#include <stdio.h>。 函數原型:

1 int scanf(const char * restrict format,...);
2 // format表示輸入指令格式

例如讀取兩個整數 和 

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=0b=1,他們的ASCII碼值分別是4849,因此0<1符合ASCII值48<49

輸出結果

printf函數是格式化輸出函數,調用格式為: printf("<格式化字符串>", <參量表>),與scanf一樣被定義在被聲明在頭文件stdio.h里。

函數原型:

1 extern int printf(const char *format,...);

另外,cout函數是C++編程語言互換流中的標准輸出流,需要iostream支持。 在算法競賽中,printf格式化輸出函數對程序結果的指定輸出來說是非常方便實用的。

編程要求

本關的編程任務是補全右側代碼片段mainBeginEnd中間的代碼,具體要求如下:

  • mian中,完成兩個整數ab的讀取,並且比較他們的大小,最后輸出這兩個整數的升序序列。

測試說明

平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。

以下是平台的測試樣例:

測試輸入:2 1

預期輸出:1 2

輸入格式:兩個整數 ab

輸出格式:輸出兩個整數的升序,中間空格隔開,末尾換行。


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關:牛刀小試

任務描述

本關任務:編寫一個程序實現三個整數abc的大小比較,並完成數據讀取、運算分析和輸出結果三步曲。

相關知識

為了完成本關任務,你需要掌握:1.三個數比較。

三個數比較

三個數abc的比較方法比兩個數的比較方法稍微復雜一點,但仍然是簡單的,例如以下兩種思路:

  • 三個數共3x2x1六種排列,暴力判斷a<b && b<cc<b && b<a六種排列。
  • 先判斷一個最小值a<b && a<c,若滿足再判斷b<c還是c<b

編程要求

本關的編程任務是補全右側代碼片段mainBeginEnd中間的代碼,具體要求如下:

  • main中,完成三個整數abc的讀取,並且比較他們的大小,最后輸出這三個整數的升序序列。

測試說明

平台將自動編譯補全后的代碼,並生成若干組測試數據,接着根據程序的輸出判斷程序是否正確。

以下是平台的測試樣例:

測試輸入:3 2 1

預期輸出:1 2 3

輸入格式:三個整數abc

輸出格式:輸出三個整數的升序,中間空格隔開,末尾換行。


開始你的任務吧,祝你成功!

 

 

 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. 比較相鄰的元素:若第一個比第二個大,則交換;

    2. 遍歷開始第一對到結尾最后一對,執行步驟1

    3. 重復步驟1~2,直到排序完成。

  • 可改進的冒泡排序:第一趟排序之后最后一個元素是最大的,因此下一趟遍歷只需執行到倒數第二對。

編程要求

本關的編程任務是補全右側代碼片段mainBeginEnd中間的代碼,具體要求如下:

  • 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

矩形相關概念

  • 矩形中心點:對角線的交點
  • 矩形面積:矩形長乘以寬的結果
  • 矩形周長:矩形四條邊的長度和

編程要求

本關的編程任務是補全右側代碼片段areaperimetercenterBeginEnd中間的代碼,具體要求如下:

  • 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 }
點擊查看代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM