ACM程序設計課程總結

知識總結

一、遞歸算法

【算法描述】
程序直接或間接調用自身的編程技巧稱爲遞歸算法。
【主要思想】把大型複雜的問題一步一步的轉化爲一個與原問題相似規模的較小的問題來求解。就是把一個不能或不好解決的大問題轉化爲一個或幾個小問題,再把這些小問題進一步分解成更小的小問題。
【關鍵步驟】
分析問題找出大問題與小問題之間的關係,寫出他們的前後關係式。然後最關鍵的是找出遞歸的定義和遞歸的終止條件。

這種算法的效練很低,一般不用。

這是之前寫過的遞歸的總結 遞歸算法總結
還有一些經典的例題,能幫助理解遞歸的思想
1.【菲波那契數列】 http://ybt.ssoier.cn:8088/problem_show.php?pid=1201
2.【Pell數列】http://ybt.ssoier.cn:8088/problem_show.php?pid=1202
3.【漢諾塔問題】http://ybt.ssoier.cn:8088/problem_show.php?pid=1205
4.【放蘋果】http://ybt.ssoier.cn:8088/problem_show.php?pid=1206
5.】求最大公約數問題】http://ybt.ssoier.cn:8088/problem_show.php?pid=1207

二、貪心算法

【基本概念】
在求最優解問題的過程中,依據某種貪心標準,從問題的初始狀態出發,直接去求每一步的最優解,通過若干次的貪心選擇,最終得出整個問題的最優解,這種求解方法就是貪心。
【注意】貪心算法不是從整體上考慮問題,它所做出的選擇只是在某種意義上的局部最優解,而由問題自身的特性決定了該題運用貪心算法可以得到最優解。

這是之前對貪心進行的總結 貪心算法總結
還有一些寫過的題目的題解
1.貪心題目
2.尋找平面上的極大點
3.拼點遊戲
4.A and B and Team Training
5.Cinema Line
6.BerSU Ball
7.Chewbaсca and Number
8.Random Teams
9.Color the Fence
10.Anton and currency you all know
11.Kyoya and Colored Balls

三、動態規劃

我感覺dp這部分是很困難的,當時學習的時候沒少下功夫
【基本思想】
將待求解問題分解成若干個子問題,先求解子問題,然後從這些子問題的解得到原問題的解。
【解題步驟】
1、判斷問題是否具有最優子結構性質,若不具備則不能用動態規劃
2、把問題分成若干個子問題
3、建立狀態轉移方程
4、找出邊界條件
5、將已知邊界值帶入方程
6、遞推求解

dp代碼量一般較少,但是思維量很大,需要很強的邏輯思維能力,我覺得數學功底一定要紮實,最關鍵的就是找到遞推公式

1.線性dp
顧名思義,就是在線性區間上去解決問題,即線性區間上的最優化問題。這是最基礎的,主要理解好問題的子問題來寫出轉移方程,確定的邊界條件就ok了

經典題目:
https://blog.csdn.net/SDAU_LGX/article/details/105186003

2.區間dp
就是線性動態規劃的擴展,它在分階段地劃分問題時,與階段中元素出現的順序和由前一階段的區間中哪些元素合併而來有很大的關係。

主要思想就是在小區間進行 DP 得到最優解,然後再利用小區間的最優解合併求大區間的最優解。往往會枚舉區間,將區間分成左右兩部分,再求出左右區間進行合併操作

3.揹包問題

問題可以描述爲:給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內,我們如何選擇,才能使得物品的總價格最高。問題的名稱來源於如何選擇最合適的物品放置於給定揹包中。

也可以將揹包問題描述爲決定性問題,即:在總重量不超過W的前提下,總價值是否能達到V?

a.01揹包

【概述】
0-1揹包問題是最基本的揹包問題,它包含了揹包問題中設計狀態、方程的最基本思想,另外,別的類型的揹包問題往往也可以轉換成0-1揹包問題求解。

特點:每種物品僅有一件,可以選擇放或不放。

b.完全揹包

它的特點就是物品不限量

c.多重揹包
它是上面的兩種情況的綜合,給出了數目的限制。

一些題目的題解
1.https://blog.csdn.net/SDAU_LGX/article/details/105587960
2.https://blog.csdn.net/SDAU_LGX/article/details/105639454

四、分治算法

1.二分
【概述】
二分查找又稱折半查找,其要求線性表中的記錄必須按關鍵碼有序,且必須採用順序存儲。

其基本思想是:用給定值 k 先與中間結點的關鍵字比較,中間結點把線形表分成兩個子表,若相等則查找成功;若不相等,再根據 k 與該中間結點關鍵字的比較結果確定下一步查找哪個子表,這樣遞歸進行,直到查找到或查找結束髮現表中沒有這樣的結點。

while(high - low > 1.0e-6)||(left<=right)
{
	 mid = (high + low)/2;
    if(Caculate(mid)<x)
        low=mid;
    else
        high=mid;
}

不過二分很少單獨考察,都是結合着其他的一些知識來運用,主要是優化時間

經典題目及題解
https://blog.csdn.net/SDAU_LGX/article/details/105813615
2.三分
【概述】
三分法是二分法的擴展,其用於求凸性或凹形函數的極值,當通過函數本身表達式並不容易求解時,就可以用三分查找來不斷逼近求解。

其原理爲:函數中存在一個點 x 是最值,對於 x 的左邊,滿足單調上升(下降),右邊滿足單調下降(上升),然後進行兩次二分,使得不斷的逼近這個 x 點,最後求得答案。

【基本思想】
類似二分的定義 Left 和 Right,對於 [L,R],先找出 lmid,緊接着再找出 rmid,然後比較兩者誰更優,然後捨去不優的。

mid=Left+(Left-Right)/3
mid_mid=Right-(Right-Left)/3
若 lmid 靠近極值點,則 Right=rmid,若 rmid 靠近極值點,則 Left=lmid;

在這裏插入圖片描述

若在三分過程中,遇到 f(lmid)=f(rmid) 時,若函數嚴格單調,那麼令 left=lmid 或令 right=rmid 均可,若函數不嚴格單調,即在函數中存在一段函數值相等的區間,將無法判斷定義域左右邊界該如何縮小,三分法也就不再適用。

五、數論

數論,是專門研究整數的純數學的分支,是知識量非常龐大的一部分,這部分也非常難掌握,需要很紮實的數學基本功,對數學能力要求非常非常高

有很多很多的知識需要掌握

篩選法—埃氏篩法(Eratosthenes篩選法)求素數
埃氏篩法分解因數
最大公約數GCD歐幾里得算法
最小公倍數的計算
快速冪
費馬小定理
歐拉定理
歐拉定理的推論
裴蜀定理
擴展歐幾里得算法
逆元及求解
容斥原理
歐拉函數
線性同餘方程
中國剩餘定理

數論這裏就貼一個大佬寫的博客 數論知識點

六、STL的簡單應用

1.string類

string類是c++中的字符串類型。
【頭文件】

#include<string>

【輸入方式】
主要輸入方式有兩種,分別爲cin和getline

1.cin

	string s;
	cin>>s;

注:cin輸入的字符串不能含空格

2.getline

	string s;
	getline(cin,s);

【各種簡單操作】

string s1, s2;			//定義兩個字符串對象
string s3 = "Hello, World!";	//創建s3,並初始化
string s4("I am ");
s2 = "Today";				//賦值
s1 = s3 + " " + s4;			//字符串連接
s1 += " 5 ";				//末尾追加
cout << s1 + s2 + "!" <<endl;	//輸出字符串內容

【常用功能函數】

	string s;
	s.size()//返回字符串的長度
	s.empty()//判斷字符串是否爲空 若空,返回ture

在string對象中,可用運算符比較兩個字符串的大小
兩個string相等意味着它們的長度相同,並且所包含的字符也完全相同
字符串的大小關係依照字典順序定義且區分大小寫字母

	string s1 = "hello";		
	string s2 = "hello world";	// s2 > s1
	string s3 = "Hello";		// s3 < s1, s3 < s2

像字符數組那樣,下標運算符可以訪問string對象中指定位置的字符

2.棧(stack)
【描述】
棧是一種特殊的數據結構,遵循先進後出的原則,只能在棧頂操作元素

【頭文件】

#include<stack>

【定義】

stack<data_type> stack_name

stack<int>s;

【基本功能函數】

	empty() //返回bool型,表示棧內是否爲空 (s.empty() )
	size() // 返回棧內元素個數 (s.size() )
	top() //返回棧頂元素值 (s.top() )
	pop() // 移除棧頂元素(s.pop(); )
	push(data_type a) // 向棧壓入一個元素 a(s.push(a);

3.隊列(queue)
【描述】
隊列是一種先進先出的數據結構,從底端加入元素,從頂端取出元素

【頭文件】

#include<queue>

【定義】
queue<date_type>queue_name

例如

queue<int>q;

【常用功能函數】

	empty() //返回bool型,表示queue是否爲空 (q.empty() )
	size() //返回queue內元素個數 (q.size() )
	front() //返回queue內的下一個元素 (q.front() )
	back() // 返回queue內的最後一個元素(q.back() )
	pop() // 移除queue中的一個元素(q.pop(); )
	push(data_type a) // 將一個元素a置入queue中(q.push(a)

4.動態數組(vector)

【頭文件】

#include<vector>

【定義】
vector<date_type>vector_name

例如

vector<int>v;

【常用功能函數】

	empty() // 返回bool型,表示vector是否爲空 (v.empty() )
	size() // 返回vector內元素個數 (v.size() )
	push_back(data_type a) //將元素a插入最尾端
	pop_back() //將最尾端元素刪除
	v[i] //類似數組取第i個位置的元素(v[0])

5.優先隊列(priority_queue)
【描述】
優先隊列是一個擁有權值觀念的queue,自動依照元素的權值排列,權值最高排在前面

【頭文件】

#include<queue>

【定義】
priority_queue <data_type> priority_queue_name

例如

priority_queue<int>q

【常用功能函數】

	q.push(elem) //將元素elem置入優先隊列
	q.top() //返回優先隊列的下一個元素
	q.pop() //移除一個元素
	q.size() //返回隊列中元素的個數
	q.empty() //返回優先隊列是否爲空

學習這門課後的感想

ACM課程到現在已經結束了,回想起第一堂課聽到費老師講課和對ACM的憧憬,彷彿就在昨天。還記得當初ACM新生賽輕輕鬆鬆拿了個一等獎,於是信心滿滿地選了這門課。直到上了幾次課把基礎的地方學完開始進階的時候,瞬間感受到什麼叫ACM…… 感受到智商碾壓。
在我看來,ACM的本質就是數學,數學素養真的很重要,我因爲本身數學不是太好,所以有些地方理解起來比較喫力,於是有些題目一遍一遍的WA,有時候真有種欲哭無淚的感覺。期間有好幾次覺得太難而想要放棄,但最終還是堅持下來。
一學期的課程讓我學到了很多知識,讓我養成了很多好習慣。同時也意識到了自己很多的不足。現在就接觸了一些基礎的算法知識,到大二就會輕鬆很多;還有刷題,提高了編程能力,感覺自己的寫代碼的速度明顯的提高了。我也養成了很多好的習慣,比如寫博客,然後慢慢的其他的科目也會每週都複習一下知識,寫一個總結;還有由於題目都是英文的,所以每天都會背單詞;也提升了信息查找的能力,學會了怎麼在網上準確快速的查找信息。當然我也清楚,如果以後還想在這條路上走下去,這些知識是遠遠不夠的,只是學習了一些基礎知識,才達到剛剛入門的程度。
再說說codeforces上的比賽,剛開始打的時候每場比賽也就是出一道題,分數刷刷的往下掉,打到現在,出題的速度也比之前快了不少,平均每場比賽能出2-3題,分數也開始回升,能明顯感受到自己的進步,覺得之前的努力沒有白費。
ACM課程雖然已經結束了,但學習還遠沒有結束。ACM課程讓我意識到自己現在所接觸到的只是知識大海的冰山一角,還有大把知識供我學習、領悟,我要做的就是虛心求教,沉心學習。
革命尚未成功,同志仍需努力!!
最後,感謝費老師這一學期的淳淳教導,您辛苦了!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章