修改code completion快捷鍵位CTRL+ENTER,幫助提示函數名稱
修改命令行提示符的屬性,開啓快速編輯模式,方便調試
添加c++11語言標準支持
開啓代碼調試功能
對輸入的字符串進行切割時,可以使用scanf按照指定格式分別輸入達到切割效果,比如:
//對於這樣的輸入
3-10 99
11-5 87
102-1 0
//對於這種格式不絕對統一的字符串,可以自己構造相應的scanf分割對應的數據
scanf("%d-%d %d", &t, &num, &score);
對於需要進行除法運算的變量,並且有精確度要求的時候,可以這樣
double grade =0;
//其中fullscore數組爲int類型,在*1.0小數之後,自動轉換爲浮點型
grade += fullscore[j] * 1.0 / 2;
//或者這樣強轉
grade += (double)fullscore[j]/2;
如果在getline讀取行之前還有其它的輸入字符(不管是字符還是整數),則需要保證在調用getline函數之前,使用getchar()函數讀取一次回車符,然後再調用
#include<iostream>
using namespace std;
int main() {
char n;
scanf("%c",&n);
getchar();
string str;
getline(cin,str);
cout<<str;
}
散列表的應用:在需要進行遍歷數組內容,判斷某一個元素是否存在時,可以使用一個大數組,初始化爲0,錄入數據時,相應數據(把下標看成數據)的內容修改爲1,這樣判斷的時候直接判斷a[element]==1即可,其中element爲錄入的數據。這樣就把O(n)級別的時間複雜度降到了O(1)
atoi&stoi(stol)&strtol區別
即使不記得也沒關係,只要記住以下用法即可
//數字型變量轉字符串
to_string();//c++全局函數
//字符串轉數字
stoi();//to int
stol();//to long
stof();//to float
//都需要導入#include <string>
四捨五入,可以先double +0.5然後轉int取整數部分,也可以用cmath
的函數round()
數組,字符串或其它常用stl容器大規模清零或者填充數據可以使用fill()
函數
// fill algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::fill
#include <vector> // std::vector
int main () {
std::vector<int> myvector (8); // myvector: 0 0 0 0 0 0 0 0
std::fill (myvector.begin(),myvector.begin()+4,5); // myvector: 5 5 5 5 0 0 0 0
std::fill (myvector.begin()+3,myvector.end()-2,8); // myvector: 5 5 5 8 8 8 0 0
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
output
myvector contains: 5 5 5 8 8 8 0 0
將十進制a轉換爲b進制數,當a不爲0時,將a%b從後往前倒序保存下來,每次保存後將a/b。這樣倒序保存的數就是十進制a在b進制下的結果。
進制互轉代碼參考如下
#include<iostream>
#include<cstdlib>
using namespace std;
int main(){
//把8進制的17轉化爲10進制打印輸出
string str = "17";
char *tmp ;
long result = strtol(str.c_str(),&tmp,8);
cout<<result;
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
//digital爲10進制數,r爲需要轉換的目標進制,返回目標進制數
string dtox(int digital,int r){
string result="";
const char s[37]="0123456789abcdefghijklmnopqrstuvwxyz";
if(digital==0){
return "0";
}
while(digital!=0){
int tmp =digital%r;
result+=s[tmp];
digital/=r;
}
reverse(result.begin(),result.end());
return result;
}
int main(){
cout<<"十進制10轉爲16進制結果:"<<dtox(10,16)<<endl;
cout<<"十進制10轉爲8進制結果:"<<dtox(10,8)<<endl;
cout<<"十進制10轉爲2進制結果:"<<dtox(10,2)<<endl;
cout<<"十進制10轉爲10進制結果:"<<dtox(10,10)<<endl;
}
儘量使用c++的string類
讀取整行的代碼如下
string str;
getline(cin,str);//該函數在std標準庫中,不需要引入string頭文件
c++的string類可以轉化爲c的字符數組,str.c_str();
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b){
return a*b/gcd(a,b);
}
對於一些可以事先進行預處理然後用散列表來求解的問題,可以大大減少時間複雜度。比如一個需要大量查詢斐波那契數列的問題中,我們可以事先把前N個斐波那契數列求解出來然後放到散列表中進行保存,之後的查詢就都是O(1)的時間複雜度。
▲多利用位運算來求解交集,並集,差集,可以大大減少時間複雜度,降低編碼難度。
素數的判斷
bool isPrime(int n){
if(n <= 1) return false;
int sqr = (int)sqrt(1.0*n);
for(int i = 2;i<=sqr; i++){
if(n%i==0) return false;
}
return true;
}
常用C++ STL容器
C++ container
- Sequence containers
- Sequence container adapters
- Associative containers
- Unordered associative containers
- unique key
- same key
algorithm頭文件常用函數
algorithm
- max
- min
- abs
- swap
- reverse
- is_permutation
- next_permutation
- prev_permutation
- fill
- sort
- lower_bound
- upper_bound
大數組必須定義爲全局變量
字符數組要多開一個單位
string.find()返回的是下標的值,沒有找到用==string::npos
dev c++調試代碼時,查看vector容器的內容
同時存在邊權和點權的最短路徑問題,求最短路徑條數以及最大點權和、打印最短路徑?
- 用一遍Dijkstra算法即可
- dis[i]表示從出發點到i結點最短路徑的路徑長度
- num[i]表示從出發點到i結點最短路徑的條數
- w[i]表示從出發點到i結點點權的數目之和
- path[i]表示從出發點到i結點的前驅結點,利用棧(或者遞歸)打印路徑即可
圖的初始化
-
如果是無向圖,需要注意初始化邊的時候,是有兩條邊的,不能漏掉了
-
沒有邊的情況(包括兩種情況,1.頂點v,w之間不存在邊,2.頂點v本身沒有到達自己的邊),初始化爲0,如果是初始化爲-1,則判斷邊是否存在的時候需要注意G[i][j]<0而不是直接if(G[i][j]),這兩種判斷一個是判斷0,一個是判斷<0
-
圖的初始化,可以用fill函數,具體用法可以參考如下
//必須添加algorithm頭文件 #include<algorithm> //在內存地址區間[first,last)範圍內,填充x fill(first,last,x); //但是特別注意二維數組的填充 int arr[2][2]; fill(arr[0],arr[0]+4,0); /* 這裏需要注意的是,arr[0]表示的纔是整個二維數組的起始地址,而不是arr,另外,這個區間是左閉右開區間!!! */
不僅是圖的初始化, 其它的輔助數組也可以用fill函數初始化,比如說path數組(用於記錄頂點w的前驅頂點,打印最短路徑),dist數組(用於記錄出發點到頂點w的最短路徑),num數組(用於記錄從出發點到頂點w的最短路徑條數),w數組(用於記錄從出發點到頂點w的點權之和)等。
-
在真正進行Dijkstra算法之前,先檢查下面這些數據是否都已經初始化好了
1.初始化圖 2.初始化路徑 3.初始化距離 4.初始化收錄情況 5.初始化點 6.初始化出發點,以及出發點的鄰接點的路徑和距離信息
最短路徑擴展問題
-
要求數最短路徑有多少條
- count[s] = 1;
- 如果找到更短路:count[W]=count[V];
- 如果找到等長路:count[W]+=count[V];
-
要求邊數最少的最短路
- count[s] = 0;
- 如果找到更短路:count[W]=count[V]+1;
- 如果找到等長路:count[W]=count[V]+1;
-
存在點權
比如救火問題,多條最短路徑,選擇點權最大的那條
for(int i = 0; i < n; i++) { int u = -1, minn = inf; for(int j = 0; j < n; j++) { if(visit[j] == false && dis[j] < minn) { u = j; minn = dis[j]; } } if(u == -1) break; visit[u] = true; for(int v = 0; v < n; v++) { if(visit[v] == false && e[u][v] != inf) { if(dis[u] + e[u][v] < dis[v]) { dis[v] = dis[u] + e[u][v]; num[v] = num[u]; w[v] = w[u] + weight[v]; } else if(dis[u] + e[u][v] == dis[v]) { num[v] = num[v] + num[u]; if(w[u] + weight[v] > w[v]) w[v] = w[u] + weight[v]; } } } }
-
邊權不唯一
比如旅遊規劃問題,存在多條最短路徑時,選擇花費最少的
void Dijkstra( Vertex s ) { while (1) { V = 未收錄頂點中dist最小者; if ( 這樣的V不存在) break; collected[V] = true; for ( V 的每個鄰接點W ) if ( collected[W] == false ) if ( dist[V]+E<V,W> < dist[W] ) { dist[W] = dist[V] + E<V,W> ; path[W] = V; cost[W] = cost[V] + C<V,W> ; } else if ( (dist[V]+E<V,W> == dist[W]) && (cost[V]+C<V,W> < cost[W]) ) { cost[W] = cost[V] + C<V,W> ; path[W] = V; } } }
algorithm常用函數補充 所有的range都是左閉右開區間 //判斷range1是否爲range2(長度length2>=length1)的子序列,可以完全相等 is_permutation(first1,last1,first2);
//查找range2在range1中的位置 search(first1,last1,first2,last2);
//交換a和b的值 swap(a,b);
//填充range fill(first,last,value);
//reverse反轉一個range reverse(first,last);
//判斷range是否有序【升序asc】 is_sorted(first,last);
//獲取從那個位置開始無序 is_sorted_until(foo.begin(),foo.end());
//一個有序range插入新元素x的最小插入位置 lower_bound (v.begin(), v.end(), 20);
//一個有序range插入新元素x的最大插入位置 upper_bound (v.begin(), v.end(), 20);
//合併兩個range到一個新容器中 std::merge (first,first+5,second,second+5,v.begin());
//獲取min std::min(1,2)
//獲取max std::max(1,2)
//獲取min_element std::cout << "The smallest element is " << *std::min_element(myints,myints+7) << '\n';
//獲取max_element std::cout << "The largest element is " << *std::max_element(myints,myints+7) << '\n';
//獲取一個range的一個序列 int main () { int myints[] = {1,2,3};
std::sort (myints,myints+3);
std::cout << "The 3! possible permutations with 3 elements:\n"; do { std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n'; } while ( std::next_permutation(myints,myints+3) );//對應的就是更大的序列
std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
return 0; } 輸出結果 The 3! possible permutations with 3 elements: 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 After loop: 1 2 3
類似的還有 std::prev_permutation(myints,myints+3) 返回一個bool true if the function could rearrange the object as a lexicographicaly smaller permutation(字典序更小的子序列). Otherwise, the function returns false to indicate that the arrangement is not less than the previous, but the largest possible (sorted in descending order).
開考前,可以先用記事本把一些常用的頭文件寫下來
注意求平均值的時候是否需要四捨五入,如果需要+0.5即可
排名問題,如果兩個人分數一樣,那麼排名也是一樣的,比如 第一種情況: 1,1,1,4,5,6
stu[0].rank[flag] = 1;
for(int i = 1; i < n; i++) {
stu[i].rank[flag] = i + 1;
if(stu[i].score[flag] == stu[i-1].score[flag])
stu[i].rank[flag] = stu[i-1].rank[flag];
}
第二種情況: 1,2,3,4,5 這種比較簡單,可以直接使用for循環,或者while循環,臨時變量每次自增1即可
通常都是第一種情況,如果是第二種情況的話,很可能會附加排序字段
fill函數對於重置exist,flag,visit等類型的數組很方便,也省時間,一般只在fill函數無法滿足要求時才考慮使用遍歷重置數組
求圖的連通分量的個數
void dfs(int node) {
visit[node] = true;
for(int i = 1; i <= n; i++) {
if(visit[i] == false && v[node][i] == 1)
dfs(i);
}
}
int cnt = 0;
for(int j = 1; j <= n; j++) {
if(visit[j] == false) {
dfs(j);
cnt++;
}
}
還可以用並查集來求連通分量
中序和後序轉先序
#include <cstdio>
using namespace std;
int post[] = {3, 4, 2, 6, 5, 1};
int in[] = {3, 2, 4, 1, 6, 5};
void pre(int root, int start, int end) {
if(start > end) return ;
int i = start;
while(i < end && in[i] != post[root]) i++;
printf("%d ", post[root]);
pre(root - 1 - end + i, start, i - 1);
pre(root - 1, i + 1, end);
}
int main() {
pre(5, 0, 5);
return 0;
}
循環輸入
#include<iostream>
using namespace std;
int main(){
//cin循環輸入測試
int a;
//只要輸入的整數a不等於9,循環就會一直執行,直到輸入9
while(cin>>a,a!=9){
printf("%d\n",a);
}
return 0;
}
如果要在遇到換行符時退出循環,可以使用getchar()函數來判斷
#include<iostream>
using namespace std;
int main() {
//cin循環輸入測試
string tkey;
while(cin >> tkey) {
cout<<tkey<<endl;
char c = getchar();
if(c == '\n') break;
}
return 0;
}
原文出處:https://www.cnblogs.com/ericling/p/11888344.html