必須記憶的算法——記憶筆記

 高效素數打表——歐拉打表

s[i+1].find(s[i])==s[i+1].npos//  npos  表示不存在
#include<iostream>
#define maxn 100000
#define maxl 1000000
using namespace std;
int prime[maxn];
bool vis[maxl];
void get_prime(){//線性時間篩法——歐拉篩法
	int cnt=0;
	int i,j;
	for(i=2;i<maxl;i++){
		if(!vis[i]){
			prime[cnt++]=i;vis[i]=true;
		}
		for(j=0;j<cnt;j++){
			if(i*prime[j]>maxl)break;
			vis[i*prime[j]] =true;
			if(i%prime[j]==0) break; 
		}
	}
}
int main(){
	get_prime();
	for(int i=0;i<100;i++) cout<<prime[i]<<endl;
	return 0;
}

最長對稱子序列——偶數,奇數

#include<iostream>
#include<algorithm>
#include<set>
#include<cstring>
using namespace std;
int main() {
	string a;
	while (getline(cin, a)) {
		int l = a.length();
		int len = 0;
		for (int i = 0; i < l; i++) {
			for (int j = 0; i - j >= 0 && i + j < l; j++) {
				if (a[i - j] != a[i + j]) break;
				if (2 * j + 1 > len) len = 2 * j + 1;
			}
			for (int j = 0; i - j >= 0 && i + j <= l; j++) {
				if (a[i - j] != a[i + j + 1]) break;
				if (2 * j + 2 > len) len = 2 * j + 2;
			}
		}
		cout << len << endl;
	} return 0;
}

最長子序列

#include<iostream>
using namespace std;
int maxs(const int a[], int n) {
	int thissum, maxsum, j;
	thissum = maxsum = 0 ;
	for (j = 0; j < n; j++) {
		thissum += a[j];
		if (thissum > maxsum) maxsum = thissum;
		else if (thissum < 0) thissum = 0;
	}
	return maxsum;
}
int main() {
	int a[1000];
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) cin >> a[i];
	int maxss=maxs(a, n);
	cout << maxss << endl;
	system("pause");
	return 0;
}

kmp 算法 ——兩個字符串 匹配  輸出 起始 index

#include<iostream>
using namespace std;
const int maxl = 1000000;
const int maxn = 100000;
int a[maxl], b[maxn];
int n, m, f;//m 模板長度 n 匹配串長度
int nex[maxn];
void get_next() {
	int i = 0; int j = -1;
	nex[0] = -1;
	while (j < n) {
		if (j == -1 || a[i] == b[j])nex[++i] = ++j;
		else j = nex[j];
	}
}
void kmp() {
	int i =0, j =0;

	get_next();
	while (i < m) {
		if (j == -1 || a[i] == b[j])
		{
			i++; j++;
		}
		else j = nex[j];
		if (j == n) {
			cout << i - n + 1 << endl;
			f = 0;
			break;
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--) {
		f = 1;
		for (int i = 0; i < m; i++) cin >> a[i];
		for (int i = 0; i < n; i++) cin >> b[i];
		kmp();
		if (f) cout << "-1" << endl;
	}return 0;
}

歐幾里得算法————求兩個數的最大公因數

unsigned int gcd(int x, int y) {//循環實現
	unsigned int rem;
	while (y > 0) {
		rem = x % y;
		x = y;
		y = rem;
	}
	return x;
}

int gcd1(int x, int y) {//遞歸實現
	return y == 0 ? x : gcd(y, x%y);
}

最小公倍數 ——藉助gcd()

int g(int x, int y) {
	return x / gcd(x, y)*y;
}// 先除法後乘法 防止數據溢出

 

對分查找————排好序的數組中查找某一元素T

int BinarySearch(const ElementType a[],ElwmentTpye T,int n){
	int low,mid,high;
	low=0;
	high=n-1;
	while(low<=high){
		mid=(low+high)/2;
		if(a[mid]<x){
			low=mid+1;
		}else if(a[mid]>x){
			high=mid-1;
		}else return mid;/* found*/
	}
	return -1;/*notfound*/
}

快速冪 

long int pow(long int x,long int n){
	if(n==0) return 1;
	if(n==1) return x;
	if(n%2){//奇數個 
		return pow(x*x,n/2)*x;
	}else return pow(x*x,n/2);//偶數個 
}

兩點間的最短路徑——固定一點到其餘所有點的最短路徑(Dijkstra算法)(沒有負邊的情況)

#include<iostream>
#include<sstream>
using namespace std;
#define M 210
#define INF 0x3f3f3f 
int arr[M][M], vis[M], dis[1010];// arr 路徑 // vis 標記數組 dis  距離
int n, m;
void Dijkstra(int src) {//一點(src) 到 其餘所有點的最短路徑
	for (int i = 0; i < n; i++) {
		vis[i] = 0; dis[i] = arr[src][i];
	}
	int temp, k;
	vis[src] = 1; dis[src] = 0;
	for (int i = 0; i < n; i++) {
		temp = INF;
		for (int j = 0; j < n; j++) {
			if (!vis[j] && temp > dis[j]) {
				temp = dis[j];
				k = j;
			}
		}

		vis[k] = 1;
		for (int j = 0; j < n; j++) {
			if (!vis[j] && dis[j] > arr[k][j] + dis[k]) dis[j] = arr[k][j] + dis[k];
		}
	}
}
void work() {
int s, t, u, v, w;
	while (cin>>n>>m) {
		for (int i = 0; i < n; i++) for(int j=0;j<n;j++) arr[i][j] = INF;//初始化
		for (int i = 0; i < m; i++) {
			cin >> u >> v >> w;
			if(arr[u][v]>w) arr[u][v] = arr[v][u] = w;//輸入 ——輸入最短路徑 (可能路不只有一條)
		}
		cin >> s >> t;// 需要 求得 s 到 t(也可以是其他值) 的最短路徑
		Dijkstra(s);// 
		if (dis[t] != INF) cout<< dis[t]; else cout << "-1";
		puts("");
	}
}
int main() {
	work();
	
	system("pause");
	return 0;
}
//Dijkstra 算法的另一種寫法
#include<iostream>
#include<cmath>
#include<math.h>
#include<sstream>
#include<cstring>
using namespace std;
#define M 110
#define INF 0x3f3f3f
int arr[M][M], vis[M], dis[1010];//三個數組都需要初始化
/*
arr數組 初始化 目的: 保證在輸入的 兩地之間 只記錄最短的距離 (可能兩地有不止一條路)
vis  標記是否被讀取 走過的路不再重複
dis  初始爲最遠  
*/
int n, m;// n 頂點數
int min(int x, int y) {
	return x < y ? x : y;
}
void Dijkstra(int src) {//一點 到 其餘所有點的最短路徑
	memset(vis, 0, sizeof(vis));
		memset(dis, INF, sizeof(dis));
		dis[src] = 0;
		while (true) {
			int v = -1;
			//從尚未選擇的頂點中選一個距離最小的點
			for (int i = 1; i <= n; i++) {
				if (!vis[i] && (v ==-1 || dis[i] < dis[v])) v = i;
			}
			if (v == -1) break;
			vis[v] = 1;
			for (int i = 1; i <= n; i++) {
				dis[i] = min(dis[i],dis[v] + arr[v][i]);
			}
		}
}

void work() {
int s, t, u, v, w;
	while (cin>>n>>m) {
		if (m == 0 && n == 0) break;
		for (int i = 1; i <= n; i++) for(int j=1;j<=n;j++) arr[i][j] = INF;
		for (int i = 0; i < m; i++) {
			cin >> u >> v >> w;
			if(arr[u][v]>w) arr[u][v] = arr[v][u] = w;
		}
		s = 1; t = n;
		Dijkstra(s);
		 cout << dis[t];
		puts("");
	}
}
int main() {
	work();
	
	system("pause");
	return 0;
}

最小生成樹——用於求取一棵樹上最近的聯通距離(eg: 連接所有村莊的電線最短長度)

#include <iostream>
#include<math.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 101;

int n; //節點數
int mp[N][N];//地圖
int dis[N];//存儲距離
int vis[N];//標記

int min(int x, int y) {
	return x < y ? x : y;
}
int prime(int s) //傳進起始點
{

	for (int i = 0; i < n; i++) {
		dis[i] = inf;
		vis[i] = 0;
	}
	dis[s] = 0;
	int res = 0;
	while (true) {
		int v = -1;
		for (int i = 0; i < n; i++) if (!vis[i] && (v == -1 || dis[i] < dis[v])) v = i;;
		if (v == -1) break;
		vis[v] = true;
		res += dis[v];
		for (int i = 0; i < n; i++) {
			dis[i] = min(dis[i], mp[v][i]);
		}
	}return res;
}

void work() {
	while (cin >> n) {
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++) { cin >> mp[i][j]; if (!mp[i][j]) mp[i][j] = inf; }
		int num = prime(0);
		cout << num << endl;
	}
}
int main() {
	work();
	system("pause");
	return 0;
}
//法二
void prim(){
	int i,j,d[MAXV],vis[MAXV],mi,v;
	for(i=1;i<=n;i++){
		d[i]=map[1][i];
		vis[i]=0;
	}
	for(i=1;i<=n;i++){
		mi=inf;
		for(j=1;j<=n;j++)
			if(!vis[j] && d[j]<mi){
				mi=d[j];
				v=j;
			}
		vis[v]=1;
		for(j=1;j<=n;j++)
			if(!vis[j] && d[j]>map[v][j])
				d[j]=map[v][j];
	}
	for(d[0]=0,i=1;i<=n;i++) d[0]+=d[i];
 
	printf("%d\n",d[0]);
}
// 法三
const int inf = 0x3f3f3f3f;
const int N = 30;

int n; //節點數
int mp[N][N];//地圖
int dis[N];//存儲距離
int vis[N];//標記

int prime(int s) //傳進起始點
{
    int sum = 0;  //權值總和

    for(int i = 0;i < n;i ++)  //初始化起始點到各點的距離
        dis[i] = mp[s][i];

    vis[s] = 1;      

    for(int i = 1;i <= n - 1;i ++)
    {
        //  n - 1次迭代
        int minn = inf;
        int p;
        for(int j = 0;j < n;j ++)       //找到距離最小的點
        {
            if(!vis[j] && dis[j] < minn)
                minn = dis[j], p = j;
        }

        vis[p] = 1;    

        sum += minn;        //加上邊權值

        for(int j = 0;j < n;j ++)  //鬆弛操作
        {
            if(!vis[j] && dis[j] > mp[p][j])
                dis[j] = mp[p][j];
        }
    }
    return sum;
}

 

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