# 排序
# 插入排序
#include<iostream> | |
#include<cstdio> | |
#include<cmath> | |
using namespace std; | |
// 打印数列 A | |
void print(int A[],int n) { | |
for (int i = 0; i < n; i++) | |
printf("%d%c", A[i], i == n - 1 ? '\n' : ' '); | |
} | |
// 插入排序法 | |
void insertsort(int A[], int n) { | |
// 从第二个开始,往前找比当前的小的值, | |
// 比当前值大的就往后移,知道找到小于等于 A [i] 的 | |
for (int i = 1; i < n; i++) { | |
int j = i - 1; | |
int v = A[i]; | |
while (j >= 0 && A[j] > v) { | |
A[j + 1] = A[j]; | |
j--; | |
} | |
A[j + 1] = v; | |
print(A, n); | |
} | |
} | |
int main() { | |
int n, A[110]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
print(A, n); | |
insertsort(A, n); | |
return 0; | |
} |
# 冒泡
#include<iostream> | |
#include<cstdio> | |
#include<cmath> | |
using namespace std; | |
// 冒泡排序法 | |
int bubbleSort(int A[], int n) { | |
int cnt = 0; | |
// 标记是否需要继续冒泡 | |
int flag = 1; | |
for (int i = 0; flag; i++) { | |
flag = 0; | |
for (int j = n - 1; j >= i + 1; j--) { | |
// 交换两个相邻的元素 | |
if (A[j] < A[j - 1]) { | |
swap(A[j], A[j - 1]); | |
flag = 1; | |
cnt++; | |
} | |
} | |
} | |
return cnt; | |
} | |
int main() { | |
int n, A[110]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
int cnt = bubbleSort(A, n); | |
for (int i = 0; i < n; i++) | |
printf("%d%c", A[i], i == n - 1 ? '\n' : ' '); | |
printf("%d\n", cnt); | |
return 0; | |
} |
# 选择
#include<iostream> | |
#include<cstdio> | |
#include<cmath> | |
using namespace std; | |
// 选择排序法 | |
int selectionSort(int A[], int n) { | |
int cnt = 0; | |
for (int i = 0; i < n; i++) { | |
int minj = i; | |
for (int j = i; j < n; j++) { | |
if (A[j] < A[minj]) | |
minj = j; | |
} | |
if (i != minj) | |
swap(A[i], A[minj]), cnt++; | |
} | |
return cnt; | |
} | |
int main() { | |
int n, A[110]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
int cnt = selectionSort(A, n); | |
for (int i = 0; i < n; i++) | |
printf("%d%c", A[i], i == n - 1 ? '\n' : ' '); | |
printf("%d\n", cnt); | |
return 0; | |
} |
# 稳定
#include<iostream> | |
#include<cstdio> | |
#include<cmath> | |
using namespace std; | |
struct Card { | |
char suit, value; | |
}; | |
// 冒泡排序法 | |
void bubble(struct Card A[], int n) { | |
// 标记是否需要继续冒泡 | |
int flag = 1; | |
for (int i = 0; flag; i++) { | |
flag = 0; | |
for (int j = n - 1; j >= i + 1; j--) { | |
// 交换两个相邻的元素 | |
if (A[j].value < A[j - 1].value) { | |
swap(A[j], A[j - 1]); | |
flag = 1; | |
} | |
} | |
} | |
} | |
// 选择排序法 | |
void selection(struct Card A[], int n) { | |
for (int i = 0; i < n; i++) { | |
int minj = i; | |
for (int j = i; j < n; j++) { | |
if (A[j].value < A[minj].value) | |
minj = j; | |
} | |
if (i != minj) | |
swap(A[i], A[minj]); | |
} | |
} | |
// 冒泡排序法是稳定排序,选择排序后的花色和其比较则可得知排序是否稳定的 | |
bool isStable(struct Card C1[], struct Card C2[], int n) { | |
for (int i = 0; i < n; i++) { | |
if (C1[i].suit != C2[i].suit) | |
return false; | |
} | |
return true; | |
} | |
// 打印输出 | |
void print(struct Card C[], int n) { | |
for (int i = 0; i < n; i++) { | |
printf("%c%c%c", C[i].suit, C[i].value, i == n - 1 ? '\n' : ' '); | |
} | |
} | |
int main() { | |
Card C1[100], C2[100]; | |
int n; | |
scanf("%d", &n); | |
getchar(); | |
for (int i = 0; i < n; i++) { | |
scanf("%c%c", &C1[i].suit, &C1[i].value); | |
getchar(); | |
C2[i] = C1[i]; | |
} | |
// 对于 C1 数列进行冒泡排序,对 C2 数列进行选择排序,然后比较两者排序后的花色 | |
// 则可得知选择排序是否稳定 | |
bubble(C1, n); | |
selection(C2, n); | |
print(C1, n); | |
printf("Stable\n"); | |
print(C2, n); | |
if (isStable(C1, C2, n)) | |
printf("Stable\n"); | |
else | |
printf("Not stable\n"); | |
return 0; | |
} |
# 希尔
#include<iostream> | |
#include<cstdio> | |
#include<vector> | |
using namespace std; | |
//g 数组 | |
vector<int>G; | |
long long cnt; | |
int A[1000000 + 10]; | |
// 间隔为 g 的插入排序 | |
void insertionSort(int A[], int n, int g) { | |
for (int i = g; i < n; i++) { | |
int v = A[i]; | |
int j = i - g; | |
while (j >= 0 && A[j] > v) { | |
A[j + g] = A[j]; | |
j -= g; | |
cnt++; | |
} | |
A[j + g] = v; | |
} | |
} | |
// 希尔排序 | |
void shellsort(int A[], int n) { | |
for (int i = G.size() - 1; i >= 0; i--) { | |
insertionSort(A, n, G[i]); | |
} | |
} | |
// 生成 g 数组 | |
void getArray(int n) { | |
for (int h = 1; h <= n;) { | |
G.push_back(h); | |
h = 3 * h + 1; | |
} | |
} | |
int main() { | |
int n; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
getArray(n); | |
shellsort(A,n); | |
int len = G.size(); | |
printf("%d\n", len); | |
for (int i = len - 1; i >= 0; i--) | |
printf("%d%c", G[i], i == 0 ? '\n' : ' '); | |
printf("%lld\n", cnt); | |
for (int i = 0; i < n; i++) | |
printf("%d\n", A[i]); | |
return 0; | |
} |
# 数据结构
# 栈
/* 实现栈的功能 */ | |
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
// 实现栈的功能 | |
//top 是指向栈顶的指针, s 是实现栈结构的数组 | |
int top, S[1000]; | |
// 将 x 压入栈的操作 | |
void push(int x) { | |
//top 加 1 之后将元素插入到 top 所指的位置 | |
S[++top] = x; | |
} | |
// 将栈顶元素返回并删除 | |
int pop() { | |
top--; | |
return S[top + 1]; | |
} | |
// 字符转数字 | |
int CharToInt(char s[]) { | |
int ans = 0, i = 0; | |
while (s[i] != '\0') { | |
ans = ans * 10 + s[i] - '0'; | |
i++; | |
} | |
return ans; | |
} | |
int main() { | |
char s[1000]; | |
int a, b; | |
// 清空栈 | |
top = 0; | |
while(scanf("%s",s)!=EOF){ | |
if (s[0] == '+') { | |
b = pop();a = pop(); | |
push(a + b); | |
}else if (s[0] == '-') { | |
b = pop(); a = pop(); | |
push(a - b); | |
}else if (s[0] == '*') { | |
b = pop(); a = pop(); | |
push(a * b); | |
}else { | |
push(CharToInt(s)); | |
} | |
} | |
printf("%d\n",pop()); | |
return 0; | |
} |
# 队列
/* 实现队列功能 */ | |
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
using namespace std; | |
const int maxx = 100000 + 10; | |
struct task { | |
// 任务的名字和耗费的时间 | |
char name[100]; | |
int t; | |
}; | |
task Queue[maxx]; | |
// 指向队头和队尾的指针 | |
int head, tail; | |
// 判断循环队列是否已满 | |
bool isFull() { | |
return head == (tail + 1) % maxx; | |
} | |
// 判断循环队列是否为空 | |
bool isEmpty() { | |
return head == tail; | |
} | |
// 将元素 x 添加到队列的末尾 | |
void enqueue(task x) { | |
Queue[tail] = x; | |
// 循环队列 | |
tail = (tail + 1) % maxx; | |
} | |
// 返回队头元素并删除 | |
task dequeue() { | |
task x = Queue[head]; | |
// 循环队列 | |
head = (head + 1) % maxx; | |
return x; | |
} | |
int main() { | |
int n, q; | |
scanf("%d %d", &n, &q); | |
for (int i = 0; i < n; i++) { | |
scanf("%s %d", Queue[i].name, &Queue[i].t); | |
} | |
// 当前已经有 n 个元素 | |
head = 0; tail = n; | |
// 当前时间 | |
int nowtime = 0; | |
while (!isEmpty()) { | |
// 取出队头 | |
task u = dequeue(); | |
// 执行时间片 p 和 所需要时间 u.t | |
int c = min(q, u.t); | |
// 任务执行了 c ms | |
u.t -= c; | |
// 当前时间加上 c ms | |
nowtime += c; | |
// 任务还没做完,加入到队尾 | |
if (u.t > 0) { | |
enqueue(u); | |
} | |
else { // 任务已经完成,打印出结果 | |
printf("%s %d\n", u.name, nowtime); | |
} | |
} | |
return 0; | |
} |
# 链表
/* 实现双向链表功能 */ | |
#include<iostream> | |
#include<cstdio> | |
#include<cstdlib> | |
#include<cstring> | |
using namespace std; | |
const int maxx = 100000 + 10; | |
struct Node { | |
int key; | |
Node *prev, *next; | |
}; | |
Node *nil; | |
// 链表初始化 | |
void init() { | |
nil = (Node *)malloc(sizeof(Node)); | |
//C++ nil = new Node(); | |
nil->next = nil; | |
nil->prev = nil; | |
} | |
// 从链表搜索出值为 key 的结点 O (n) | |
Node* listSearch(int key) { | |
// 从链表头结点开始访问 | |
Node *cur = nil->next; | |
while (cur != nil && cur->key != key) { | |
cur = cur->next; | |
} | |
return cur; | |
} | |
// 打印链表 | |
void printList() { | |
Node *cur = nil->next; | |
int flag = 0; | |
while (cur != nil) { | |
if (flag++ > 0) | |
printf(" "); | |
printf("%d", cur->key); | |
cur = cur->next; | |
} | |
printf("\n"); | |
} | |
// 删除结点 t | |
void deleteNode(Node *t) { | |
//t 为头结点不做处理 | |
if (t == nil) | |
return; | |
t->prev->next = t->next; | |
t->next->prev = t->prev; | |
free(t); | |
//C++ delete(t); | |
} | |
// 删除头结点 | |
void deleteFirst() { | |
deleteNode(nil->next); | |
} | |
// 删除尾结点 | |
void deleteLast() { | |
deleteNode(nil->prev); | |
} | |
// 删除指定的 key O (n) | |
void deleteKey(int key) { | |
deleteNode(listSearch(key)); | |
} | |
// 在链表头部添加元素 key | |
void insert(int key) { | |
Node *x = (Node *)malloc(sizeof(Node)); | |
//C++ Node *x = new Node(); | |
x->key = key; | |
x->next = nil->next; | |
nil->next->prev = x; | |
nil->next = x; | |
x->prev = nil; | |
} | |
int main() { | |
int n, key, size = 0; | |
char op[20]; | |
scanf("%d", &n); | |
getchar(); | |
// 初始化链表 | |
init(); | |
for (int i = 0; i < n; i++) { | |
scanf("%s %d", op, &key); | |
if (op[0] == 'i') { | |
insert(key); | |
size++; | |
} | |
else { | |
if (strlen(op) > 6) { | |
if (op[6] == 'F') {// 删除头结点 | |
deleteFirst(); | |
} | |
else {// 删除尾结点 | |
deleteLast(); | |
} | |
} | |
else { // 删除结点 | |
deleteKey(key); | |
} | |
size--; | |
} | |
} | |
printList(); | |
return 0; | |
} |
# 标准库
/* 利用 STL 的 stack 类 */ | |
#include<iostream> | |
#include<cstdio> | |
#include<stack> | |
using namespace std; | |
// 字符转数字 | |
int CharToInt(char s[]) { | |
int ans = 0, i = 0; | |
while (s[i] != '\0') { | |
ans = ans * 10 + s[i] - '0'; | |
i++; | |
} | |
return ans; | |
} | |
int main() | |
{ | |
char s[1000]; | |
int a, b; | |
stack<int> S; | |
while(scanf("%s",s)!=EOF){ | |
if (s[0] == '+') { | |
b = S.top(); S.pop(); | |
a = S.top(); S.pop(); | |
S.push(a + b); | |
}else if (s[0] == '-') { | |
b = S.top(); S.pop(); | |
a = S.top(); S.pop(); | |
S.push(a - b); | |
}else if (s[0] == '*') { | |
b = S.top(); S.pop(); | |
a = S.top(); S.pop(); | |
S.push(a * b); | |
}else { | |
S.push(CharToInt(s)); | |
} | |
} | |
printf("%d\n", S.top()); | |
return 0; | |
} | |
/* 利用 STL 的 stack 类 */ | |
#include<iostream> | |
#include<cstdio> | |
#include<stack> | |
using namespace std; | |
// 字符转数字 | |
int CharToInt(char s[]) { | |
int ans = 0, i = 0; | |
while (s[i] != '\0') { | |
ans = ans * 10 + s[i] - '0'; | |
i++; | |
} | |
return ans; | |
} | |
int main() | |
{ | |
char s[1000]; | |
int a, b; | |
stack<int> S; | |
while(scanf("%s",s)!=EOF){ | |
if (s[0] == '+') { | |
b = S.top(); S.pop(); | |
a = S.top(); S.pop(); | |
S.push(a + b); | |
}else if (s[0] == '-') { | |
b = S.top(); S.pop(); | |
a = S.top(); S.pop(); | |
S.push(a - b); | |
}else if (s[0] == '*') { | |
b = S.top(); S.pop(); | |
a = S.top(); S.pop(); | |
S.push(a * b); | |
}else { | |
S.push(CharToInt(s)); | |
} | |
} | |
printf("%d\n", S.top()); | |
return 0; | |
} | |
/* 利用 STL 的 list 类 */ | |
#include<iostream> | |
#include<cstdio> | |
#include<cstring> | |
#include<list> | |
using namespace std; | |
int main() { | |
int n, key; | |
char op[20]; | |
list<int> List; | |
scanf("%d", &n); | |
getchar(); | |
for (int i = 0; i < n; i++) { | |
scanf("%s %d", op, &key); | |
if (op[0] == 'i') { | |
List.push_front(key); | |
} | |
else { | |
if (strlen(op) > 6) { | |
if (op[6] == 'F') {// 删除头结点 | |
List.pop_front(); | |
} | |
else {// 删除尾结点 | |
List.pop_back(); | |
} | |
} | |
else { // 删除结点 | |
for (list<int>::iterator it = List.begin(); it != List.end(); it++) { | |
if (*it == key) { | |
List.erase(it); | |
break; | |
} | |
} | |
} | |
} | |
} | |
int flag = 0; | |
for (list<int>::iterator it = List.begin(); it != List.end(); it++) { | |
if (flag != 0) | |
printf(" "); | |
flag++; | |
printf("%d", (*it)); | |
} | |
printf("\n"); | |
return 0; | |
} |
# 搜索
# 线性
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
// 线性搜索 | |
bool LinearSearch(int A[], int n, int key) { | |
// 将 key 设置为数列最后一项 | |
A[n] = key; | |
int i = 0; | |
while (A[i] != key) | |
i++; | |
// 如果 i 不是 n,则代表在原来的数列中找到 key, | |
// 否则代表原来数列中没有 key,找到的是刚才插入到最后的元素 | |
return i != n; | |
} | |
int main() { | |
int n, q, key; | |
int sum = 0; | |
int A[10000 + 10]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
scanf("%d", &q); | |
for (int i = 0; i < q; i++) { | |
scanf("%d", &key); | |
if (LinearSearch(A, n, key)) | |
sum++; | |
} | |
printf("%d\n", sum); | |
} |
# 二分
/* 实现二分搜索 */ | |
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
// 二分搜索 | |
bool BinarySearch(int A[], int n, int key) { | |
int left = 0 , right = n, mid; | |
while (left < right) { | |
mid = (left + right) / 2; | |
if (key == A[mid]) | |
return true; | |
if(key > A[mid]) | |
left = mid + 1; | |
if (key < A[mid]) | |
right = mid; | |
} | |
return false; | |
} | |
int main() { | |
int n, q, key; | |
int sum = 0; | |
int A[100000 + 10]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
scanf("%d", &q); | |
for (int i = 0; i < q; i++) { | |
scanf("%d", &key); | |
if (BinarySearch(A, n, key)) | |
sum++; | |
} | |
printf("%d\n", sum); | |
} |
# 散列
#include<iostream> | |
#include<cstdio> | |
#include<cstring> | |
using namespace std; | |
typedef long long LL; | |
const LL maxx = 1000000 + 10; | |
char H[maxx][15]; | |
// 将字符转换为数值 | |
LL CharToInt(char ch) { | |
if (ch == 'A') return 1; | |
if (ch == 'C') return 2; | |
if (ch == 'G') return 3; | |
if (ch == 'T') return 4; | |
return 0; | |
} | |
// 将字符串转成数值并生成 key | |
long long getKey(char str[]) { | |
LL sum = 0, p = 1; | |
LL len = strlen(str); | |
for (long long int i = 0; i < len; i++) { | |
sum += p * CharToInt(str[i]); | |
p *= 5; | |
} | |
return sum; | |
} | |
LL h1(LL key) { | |
return key % maxx; | |
} | |
LL h2(LL key) { | |
return 1 + (key % (maxx - 1)); | |
} | |
//find 操作 | |
bool find(char str[]) { | |
LL key, h; | |
key = getKey(str); | |
for (LL i = 0;; i++) { | |
h = (h1(key) + i * h2(key)) % maxx; | |
// 找到 key | |
if (strcmp(H[h], str) == 0) return true; | |
//key 不存在 | |
else if (strlen(H[h]) == 0) return false; | |
} | |
return false; | |
} | |
//insert 操作 | |
void insert(char str[]) { | |
LL key, h; | |
key = getKey(str); | |
for (LL i = 0;; i++) { | |
h = (h1(key) + i * h2(key)) % maxx; | |
// 找到 key | |
if (strcmp(H[h], str) == 0) return ; | |
//key 不存在 | |
else if (strlen(H[h]) == 0) { | |
// 插入 | |
strcpy(H[h], str); | |
return ; | |
} | |
} | |
} | |
int main() { | |
int n, q, key; | |
char str[20], op[20]; | |
for (int i = 0; i < maxx; i++) | |
H[i][0] = '\0'; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
scanf("%s %s", op, str); | |
if (op[0] == 'i') | |
insert(str); | |
else { | |
if (find(str)) | |
printf("yes\n"); | |
else | |
printf("no\n"); | |
} | |
} | |
return 0; | |
} |
# 标准库
/* 利用 STL 的 binary_search*/ | |
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
using namespace std; | |
int main() { | |
int n, q, key; | |
int sum = 0; | |
int A[100000 + 10]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
scanf("%d", &q); | |
for (int i = 0; i < q; i++) { | |
scanf("%d", &key); | |
if (binary_search(A, A + n, key)) | |
sum++; | |
} | |
printf("%d\n", sum); | |
} |
# 递归 & 分治
# 穷竭搜索
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
int n, A[30]; | |
// 递归穷举 | |
bool solve(int i, int m) { | |
// 已经找到得到 m 的组合方式 | |
if (m == 0) | |
return true; | |
// 已经穷举过 A 的全部元素了 | |
if (i >= n) | |
return false; | |
// 分别穷举 不选 A [i] 和 选择 A [i] 的情况 | |
return solve(i + 1, m) || solve(i + 1, m - A[i]); | |
} | |
int main(){ | |
int t, M; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
scanf("%d", &A[i]); | |
} | |
scanf("%d", &t); | |
for (int i = 0; i < t; i++) { | |
scanf("%d", &M); | |
if (solve(0, M)) | |
printf("yes\n"); | |
else | |
printf("no\n"); | |
} | |
return 0; | |
} |
# 科赫曲线
#include<iostream> | |
#include<cstdio> | |
#include<cmath> | |
using namespace std; | |
const double PI = acos(-1.0); | |
struct Point{ | |
double x,y; | |
}; | |
void koch(int n, Point a, Point b) { | |
// 递归结束 | |
if (n == 0) | |
return; | |
// 三等分点 s,t ,(u 是 s,t 上方的点) | |
Point s, t, u; | |
// 角度从度转成弧度 | |
double th = PI * 60.0 / 180.0; | |
s.x = (2.0 * a.x + 1.0 * b.x) / 3.0; | |
s.y = (2.0 * a.y + 1.0 * b.y) / 3.0; | |
t.x = (1.0 * a.x + 2.0 * b.x) / 3.0; | |
t.y = (1.0 * a.y + 2.0 * b.y) / 3.0; | |
u.x = (t.x - s.x) * cos(th) - (t.y - s.y) * sin(th) + s.x; | |
u.y = (t.x - s.x) * sin(th) + (t.y - s.y) * cos(th) + s.y; | |
koch(n - 1, a, s); | |
printf("%.8lf %.8lf\n", s.x, s.y); | |
koch(n - 1, s, u); | |
printf("%.8lf %.8lf\n", u.x, u.y); | |
koch(n - 1, u, t); | |
printf("%.8lf %.8lf\n", t.x, t.y); | |
koch(n - 1, t, b); | |
} | |
int main(){ | |
Point a, b; | |
int n; | |
scanf("%d", &n); | |
// 初始化 | |
a.x = a.y = 0; | |
b.x = 100, b.y = 0; | |
printf("%.8lf %.8lf\n", a.x, a.y); | |
koch(n, a, b); | |
printf("%.8lf %.8lf\n", b.x, b.y); | |
return 0; | |
} |
# 高等排序
# 归并
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
const int MAX = 500000; | |
const int maxnum = 1000000010; | |
// 两个局部数组 | |
int L[MAX / 2 + 2], R[MAX / 2 + 2]; | |
int A[MAX], n; | |
int cnt = 0; | |
// 排序和合并 | |
void merge(int left, int mid, int right) { | |
int n1 = mid - left; | |
int n2 = right - mid; | |
for (int i = 0; i < n1; i++) L[i] = A[left + i]; | |
for (int i = 0; i < n2; i++) R[i] = A[mid + i]; | |
// 两个局部数组最后添加一个比较大的数 | |
L[n1] = R[n2] = maxnum; | |
int i = 0, j = 0; | |
// 合并 | |
for (int k = left; k < right; k++) { | |
cnt++; | |
if (L[i] <= R[j]) | |
A[k] = L[i++]; | |
else | |
A[k] = R[j++]; | |
} | |
} | |
// 分割 | |
void mergeSort(int left, int right) { | |
if (left + 1 < right) { | |
int mid = (left + right) / 2; | |
mergeSort(left, mid); | |
mergeSort(mid, right); | |
merge(left, mid, right); | |
} | |
} | |
int main() { | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
mergeSort(0, n); | |
for (int i = 0; i < n; i++) | |
printf("%d%c", A[i], i == n - 1 ? '\n' : ' '); | |
printf("%d\n", cnt); | |
return 0; | |
} |
# 分割
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
using namespace std; | |
const int MAX = 500000; | |
int A[MAX], n; | |
// 分割 | |
int partition(int p, int r) { | |
int x = A[r]; | |
int i = p - 1; | |
for (int j = p; j < r; j++) { | |
if (A[j] <= x) { | |
i++; | |
swap(A[i], A[j]); | |
} | |
} | |
swap(A[i + 1], A[r]); | |
return i + 1; | |
} | |
int main() { | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
// 记录 Ar 的下标 | |
int p = partition(0, n - 1); | |
for (int i = 0; i < n; i++) { | |
if(i == p) | |
printf("[%d]%c", A[i], i == n - 1 ? '\n' : ' '); | |
else | |
printf("%d%c", A[i], i == n - 1 ? '\n' : ' '); | |
} | |
return 0; | |
} |
# 快排
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
using namespace std; | |
const int MAX = 500000; | |
int A[MAX], n; | |
// 分割 | |
int partition(int p, int r) { | |
int x = A[r]; | |
int i = p - 1; | |
for (int j = p; j < r; j++) { | |
if (A[j] <= x) { | |
i++; | |
swap(A[i], A[j]); | |
} | |
} | |
swap(A[i + 1], A[r]); | |
return i + 1; | |
} | |
int main() { | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) | |
scanf("%d", &A[i]); | |
// 记录 Ar 的下标 | |
int p = partition(0, n - 1); | |
for (int i = 0; i < n; i++) { | |
if(i == p) | |
printf("[%d]%c", A[i], i == n - 1 ? '\n' : ' '); | |
else | |
printf("%d%c", A[i], i == n - 1 ? '\n' : ' '); | |
} | |
return 0; | |
} |
# 计数
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
using namespace std; | |
const int maxx = 2000001; | |
const int maxnum = 10010; | |
int A[maxx], B[maxx]; | |
int C[maxnum]; | |
int main() { | |
int n; | |
scanf("%d", &n); | |
// 初始化 C 数组 | |
for (int i = 0; i < maxnum; i++) | |
C[i] = 0; | |
for (int i = 0; i < n; i++) { | |
scanf("%d", &A[i + 1]); | |
// 计数到 C 数组 | |
C[A[i + 1]]++; | |
} | |
// 累加和 | |
for (int i = 1; i < maxnum; i++) | |
C[i] += C[i - 1]; | |
for (int j = 1; j <= n; j++) { | |
// 根据 C [A [j]] 确定 A [j] 存贮的下标,保存到 B 数组 | |
B[C[A[j]]] = A[j]; | |
// 存储下标往前移动 | |
C[A[j]] --; | |
} | |
for (int i = 1; i <= n; i++) | |
printf("%d%c", B[i], i == n ? '\n' : ' '); | |
return 0; | |
} |
# 标准库
# 树
# 有根数
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
#include<cmath> | |
using namespace std; | |
const int MAX = 100005; | |
const int NIL = -1; | |
struct Node { | |
int p, l, r; | |
}; | |
Node Tree[MAX]; | |
int n, Depth[MAX]; | |
void print(int u) { | |
printf("node %d: ", u); | |
printf("parent = %d, ", Tree[u].p); | |
printf("depth = %d, ", Depth[u]); | |
if (Tree[u].p == NIL) | |
printf("root, "); | |
else if (Tree[u].l == NIL) | |
printf("leaf, "); | |
else | |
printf("internal node, "); | |
printf("["); | |
// 从子结点的最左边开始遍历 | |
int c = Tree[u].l; | |
while (c != NIL) { | |
printf("%d", c); | |
if (Tree[c].r != NIL) | |
printf(", "); | |
// 跳到右侧紧邻的兄弟结点 | |
c = Tree[c].r; | |
} | |
printf("]\n"); | |
} | |
// 递归得求深度 | |
void rec(int u, int depth) { | |
Depth[u] = depth; | |
if (Tree[u].r != NIL) // 右侧兄弟设置为相同深度 | |
rec(Tree[u].r, depth); | |
if (Tree[u].l != NIL) // 最左侧子结点的深度设置为自己的深度 + 1 | |
rec(Tree[u].l, depth + 1); | |
} | |
int main() { | |
int n; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
Tree[i].p = Tree[i].l = Tree[i].r = NIL; | |
} | |
int v, num, c, l, root; | |
for (int i = 0; i < n; i++) { | |
//v 是当前结点值 ,num 是 v 结点的子结点数 | |
scanf("%d %d", &v, &num); | |
for (int j = 0; j < num; j++) { | |
scanf("%d", &c); | |
// 设置最左侧结点 和 紧邻右侧兄弟结点 | |
//l 记录的是上一个结点,将当前的结点设置为 l 的紧邻右侧结点 | |
if (j == 0) | |
Tree[v].l = c; | |
else | |
Tree[l].r = c; | |
l = c; | |
// 设置父结点 | |
Tree[c].p = v; | |
} | |
} | |
// 找出根结点 | |
for (int i = 0; i < n; i++) { | |
if (Tree[i].p == NIL) | |
root = i; | |
} | |
rec(root, 0); | |
for (int i = 0; i < n; i++) | |
print(i); | |
return 0; | |
} |
# 二叉树
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
#include<cmath> | |
using namespace std; | |
const int MAX = 100005; | |
const int NIL = -1; | |
struct Node { | |
int parent, left, right; | |
}; | |
Node Tree[MAX]; | |
int n, Depth[MAX], Height[MAX]; | |
int getDegree(int u) { | |
int deg = 0; | |
if (Tree[u].left != NIL) | |
deg++; | |
if (Tree[u].right != NIL) | |
deg++; | |
return deg; | |
} | |
void setDepth(int u, int depth) { | |
if (u == NIL) | |
return; | |
Depth[u] = depth; | |
setDepth(Tree[u].left, depth + 1); | |
setDepth(Tree[u].right, depth + 1); | |
} | |
int setHeight(int u) { | |
int h1 = 0, h2 = 0; | |
if (Tree[u].left != NIL) | |
h1 = setHeight(Tree[u].left) + 1; | |
if (Tree[u].right != NIL) | |
h2 = setHeight(Tree[u].right) + 1; | |
return Height[u] = max(h1, h2); | |
} | |
int getSibling(int u) { | |
if (Tree[u].parent == NIL) | |
return NIL; | |
// 存在左兄弟 | |
if (Tree[Tree[u].parent].left != u && Tree[Tree[u].parent].left != NIL) | |
return Tree[Tree[u].parent].left; | |
// 存在右兄弟 | |
if (Tree[Tree[u].parent].right != u && Tree[Tree[u].parent].right != NIL) | |
return Tree[Tree[u].parent].right; | |
return NIL; | |
} | |
void print(int u) { | |
printf("node %d: parent = %d, sibling = %d, degree = %d, depth = %d, height = %d, " | |
, u, Tree[u].parent, getSibling(u), getDegree(u), Depth[u], Height[u]); | |
if (Tree[u].parent == NIL) | |
printf("root\n"); | |
else if (Tree[u].left != NIL || Tree[u].right != NIL) | |
printf("internal node\n"); | |
else | |
printf("leaf\n"); | |
} | |
int main() { | |
int n; | |
int u, l, r, root; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
Tree[i].parent = Tree[i].left = Tree[i].right = NIL; | |
} | |
for (int i = 0; i < n; i++) { | |
scanf("%d %d %d", &u, &l, &r); | |
Tree[u].left = l; | |
Tree[u].right = r; | |
Tree[l].parent = u; | |
Tree[r].parent = u; | |
} | |
for (int i = 0; i < n; i++) { | |
if (Tree[i].parent == NIL) | |
root = i; | |
} | |
setHeight(root); | |
setDepth(root, 0); | |
for (int i = 0; i < n; i++) | |
print(i); | |
return 0; | |
} |
# 树的遍历
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
#include<cmath> | |
using namespace std; | |
const int MAX = 100005; | |
const int NIL = -1; | |
struct Node { | |
int parent, left, right; | |
}; | |
Node Tree[MAX]; | |
int n; | |
// 前序排序 | |
void PreorderTreeWalk(int u) { | |
if (u == NIL) | |
return; | |
printf(" %d", u); | |
PreorderTreeWalk(Tree[u].left); | |
PreorderTreeWalk(Tree[u].right); | |
} | |
// 中序排序 | |
void InorderTreeWalk(int u) { | |
if (u == NIL) | |
return; | |
InorderTreeWalk(Tree[u].left); | |
printf(" %d", u); | |
InorderTreeWalk(Tree[u].right); | |
} | |
// 后序排序 | |
void PostorderTreeWalk(int u) { | |
if (u == NIL) | |
return; | |
PostorderTreeWalk(Tree[u].left); | |
PostorderTreeWalk(Tree[u].right); | |
printf(" %d", u); | |
} | |
int main() { | |
int n; | |
int u, l, r, root; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
Tree[i].parent = Tree[i].left = Tree[i].right = NIL; | |
} | |
for (int i = 0; i < n; i++) { | |
scanf("%d %d %d", &u, &l, &r); | |
Tree[u].left = l; | |
Tree[u].right = r; | |
Tree[l].parent = u; | |
Tree[r].parent = u; | |
} | |
for (int i = 0; i < n; i++) { | |
if (Tree[i].parent == NIL) | |
root = i; | |
} | |
printf("Preorder\n"); | |
PreorderTreeWalk(root); | |
printf("\nInorder\n"); | |
InorderTreeWalk(root); | |
printf("\nPostorder\n"); | |
PostorderTreeWalk(root); | |
printf("\n"); | |
return 0; | |
} |
# 树的重建
#include<iostream> | |
#include<cstdio> | |
#include<algorithm> | |
#include<cmath> | |
#include<vector> | |
using namespace std; | |
vector<int> pre, in, post; | |
int pos; | |
int n, k; | |
void reconstruction(int left, int right) { | |
// 遍历到叶结点 | |
if (left >= right) | |
return; | |
// 当前子树的根 | |
int root = pre[pos++]; | |
// 找出当前根的值在中序数组里的下标 | |
int m = distance(in.begin(), find(in.begin(), in.end(), root)); | |
reconstruction(left, m); | |
reconstruction(m + 1, right); | |
// 存入到后序数组 | |
post.push_back(root); | |
} | |
void solve() { | |
pos = 0; | |
reconstruction(0, pre.size()); | |
for (int i = 0; i < n; i++) { | |
printf("%d%c", post[i], i == n-1?'\n':' '); | |
} | |
} | |
int main() { | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
scanf("%d", &k); | |
pre.push_back(k); | |
} | |
for (int i = 0; i < n; i++) { | |
scanf("%d", &k); | |
in.push_back(k); | |
} | |
solve(); | |
return 0; | |
} |
# 二叉搜索树
# 二叉搜索树
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
const int MAX = 100005; | |
struct Node { | |
int key; | |
Node *parent, *left, *right; | |
}; | |
Node *root, *NIL; | |
// 前序排序 | |
void PreorderTreeWalk(Node *u) { | |
if (u == NIL) | |
return; | |
printf(" %d", u->key); | |
PreorderTreeWalk(u->left); | |
PreorderTreeWalk(u->right); | |
} | |
// 中序排序 | |
void InorderTreeWalk(Node *u) { | |
if (u == NIL) | |
return; | |
InorderTreeWalk(u->left); | |
printf(" %d", u->key); | |
InorderTreeWalk(u->right); | |
} | |
void insert(int value) { | |
Node *y = NIL, *x = root; | |
Node *z = new Node(); | |
z->key = value; | |
z->left = z->right = NIL; | |
// 从根结点往下遍历 | |
while (x != NIL) { | |
y = x; | |
//z 比 x 小, 则从 x 的左侧遍历 | |
//z 比 x 大, 则从 x 的右侧遍历 | |
if (z->key < x->key) | |
x = x->left; | |
else | |
x = x->right; | |
} | |
z->parent = y; | |
// 没有父结点的是 root | |
if (y == NIL) { | |
root = z; | |
}else { | |
//z 比 y 小, 则在 y 的左侧 | |
//z 比 y 大, 则在 y 的右侧 | |
if (z->key < y->key) | |
y->left = z; | |
else | |
y->right = z; | |
} | |
} | |
int main() { | |
int n, value; | |
char s[200]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
scanf("%s", s); | |
if (s[0] == 'i') { | |
scanf("%d", &value); | |
insert(value); | |
}else { | |
InorderTreeWalk(root); | |
printf("\n"); | |
PreorderTreeWalk(root); | |
printf("\n"); | |
} | |
} | |
return 0; | |
} |
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
const int MAX = 100005; | |
struct Node { | |
int key; | |
Node *parent, *left, *right; | |
}; | |
Node *root, *NIL; | |
// 前序排序 | |
void PreorderTreeWalk(Node *u) { | |
if (u == NIL) | |
return; | |
printf(" %d", u->key); | |
PreorderTreeWalk(u->left); | |
PreorderTreeWalk(u->right); | |
} | |
// 中序排序 | |
void InorderTreeWalk(Node *u) { | |
if (u == NIL) | |
return; | |
InorderTreeWalk(u->left); | |
printf(" %d", u->key); | |
InorderTreeWalk(u->right); | |
} | |
void insert(int value) { | |
Node *y = NIL, *x = root; | |
Node *z = new Node(); | |
z->key = value; | |
z->left = z->right = NIL; | |
// 从根结点往下遍历 | |
while (x != NIL) { | |
y = x; | |
//z 比 x 小, 则从 x 的左侧遍历 | |
//z 比 x 大, 则从 x 的右侧遍历 | |
if (z->key < x->key) | |
x = x->left; | |
else | |
x = x->right; | |
} | |
z->parent = y; | |
// 没有父结点的是 root | |
if (y == NIL) { | |
root = z; | |
}else { | |
//z 比 y 小, 则在 y 的左侧 | |
//z 比 y 大, 则在 y 的右侧 | |
if (z->key < y->key) | |
y->left = z; | |
else | |
y->right = z; | |
} | |
} | |
Node * find(Node *u, int value) { | |
// 从根结点开始遍历下去 | |
while (u != NIL && u->key != value) { | |
if (value < u->key) | |
u = u->left; | |
else | |
u = u->right; | |
} | |
return u; | |
} | |
int main() { | |
int n, value; | |
Node * f; | |
char s[200]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
scanf("%s", s); | |
if (s[0] == 'i') { | |
scanf("%d", &value); | |
insert(value); | |
} | |
else if (s[0] == 'f') { | |
scanf("%d", &value); | |
f = find(root,value); | |
if (f != NIL) | |
printf("yes\n"); | |
else | |
printf("no\n"); | |
}else { | |
InorderTreeWalk(root); | |
printf("\n"); | |
PreorderTreeWalk(root); | |
printf("\n"); | |
} | |
} | |
return 0; | |
} |
#include<iostream> | |
#include<cstdio> | |
using namespace std; | |
const int MAX = 100005; | |
struct Node { | |
int key; | |
Node *parent, *left, *right; | |
}; | |
Node *root, *NIL; | |
// 前序排序 | |
void PreorderTreeWalk(Node *u) { | |
if (u == NIL) | |
return; | |
printf(" %d", u->key); | |
PreorderTreeWalk(u->left); | |
PreorderTreeWalk(u->right); | |
} | |
// 中序排序 | |
void InorderTreeWalk(Node *u) { | |
if (u == NIL) | |
return; | |
InorderTreeWalk(u->left); | |
printf(" %d", u->key); | |
InorderTreeWalk(u->right); | |
} | |
void insert(int value) { | |
Node *y = NIL, *x = root; | |
Node *z = new Node(); | |
z->key = value; | |
z->left = z->right = NIL; | |
// 从根结点往下遍历 | |
while (x != NIL) { | |
y = x; | |
//z 比 x 小, 则从 x 的左侧遍历 | |
//z 比 x 大, 则从 x 的右侧遍历 | |
if (z->key < x->key) | |
x = x->left; | |
else | |
x = x->right; | |
} | |
z->parent = y; | |
// 没有父结点的是 root | |
if (y == NIL) { | |
root = z; | |
} | |
else { | |
//z 比 y 小, 则在 y 的左侧 | |
//z 比 y 大, 则在 y 的右侧 | |
if (z->key < y->key) | |
y->left = z; | |
else | |
y->right = z; | |
} | |
} | |
Node * find(Node *u, int value) { | |
// 从根结点开始遍历下去 | |
while (u != NIL && u->key != value) { | |
if (value < u->key) | |
u = u->left; | |
else | |
u = u->right; | |
} | |
return u; | |
} | |
// 树的最小值 | |
Node *treeMinimum(Node * x) { | |
while (x->left != NIL) | |
x = x->left; | |
return x; | |
} | |
//case 3 , 搜索后一个结点 | |
Node *treeSuccessor(Node *x) { | |
if (x->right != NIL) | |
return treeMinimum(x->right); | |
Node *y = x->parent; | |
while (y != NIL && x == y->right) { | |
x = y; | |
x = y->parent; | |
} | |
return y; | |
} | |
void treeDelete(Node * z) { | |
Node *y, *x; // 要删除的对象和 y 的子结点 | |
// 确定要删除的结点 | |
if (z->left == NIL || z->right == NIL) | |
y = z; | |
else | |
y = treeSuccessor(z); | |
// 确定 y 的子结点 x | |
if (y->left != NIL) | |
x = y->left; | |
else | |
x = y->right; | |
// 让子结点链接父结点 | |
if (x != NIL) | |
x->parent = y->parent; | |
// 让父结点链接子结点 | |
if (y->parent == NIL) | |
root = x; | |
else { | |
if (y == y->parent->left) | |
y->parent->left = x; | |
else | |
y->parent->right = x; | |
} | |
// case 3 | |
if (y != z) | |
z->key = y->key; | |
delete y; | |
} | |
int main() { | |
int n, value; | |
Node * f; | |
char s[200]; | |
scanf("%d", &n); | |
for (int i = 0; i < n; i++) { | |
scanf("%s", s); | |
if (s[0] == 'i') { | |
scanf("%d", &value); | |
insert(value); | |
} | |
else if (s[0] == 'f') { | |
scanf("%d", &value); | |
f = find(root, value); | |
if (f != NIL) | |
printf("yes\n"); | |
else | |
printf("no\n"); | |
} | |
else if (s[0] == 'd') { | |
scanf("%d", &value); | |
treeDelete(find(root, value)); | |
} | |
else { | |
InorderTreeWalk(root); | |
printf("\n"); | |
PreorderTreeWalk(root); | |
printf("\n"); | |
} | |
} | |
return 0; | |
} |
# 堆
# 完全二叉堆
#include <iostream> | |
#include <cstdio> | |
using namespace std; | |
// 分别求出结点 i 的父结点,左子结点、右子结点 | |
int parent(int i) { return i / 2; } | |
int left(int i) { return 2 * i; } | |
int right(int i) { return 2 * i + 1; } | |
int main() | |
{ | |
int H[300]; | |
int n; | |
scanf("%d", &n); | |
for (int i = 1; i <= n; i++) | |
scanf("%d", &H[i]); | |
for (int i = 1; i <= n; i++) { | |
printf("node %d: key = %d, ", i, H[i]); | |
if (parent(i) >= 1) | |
printf("parent key = %d, ", H[parent(i)]); | |
if (left(i) <= n) | |
printf("left key = %d, ", H[left(i)]); | |
if (right(i) <= n) | |
printf("right key = %d, ", H[right(i)]); | |
printf("\n"); | |
} | |
return 0; | |
} |
# 最大堆
#include <iostream> | |
#include <cstdio> | |
#include <algorithm> | |
using namespace std; | |
const int maxx = 2000000; | |
int A[maxx + 1]; | |
int n; | |
void maxHeapify(int i) { | |
int left = 2 * i, right = 2 * i + 1; | |
int largest; | |
// 从左子结点、自身、右子结点选出值最大的结点,然后继续往下递归 | |
if (left <= n && A[left] > A[i]) | |
largest = left; | |
else | |
largest = i; | |
if (right <= n && A[right] > A[largest]) | |
largest = right; | |
if (largest != i) { | |
swap(A[i], A[largest]); | |
maxHeapify(largest); | |
} | |
} | |
int main() | |
{ | |
scanf("%d", &n); | |
for (int i = 1; i <= n; i++) | |
scanf("%d", &A[i]); | |
for (int i = n / 2; i >= 1; i--) | |
maxHeapify(i); | |
for (int i = 1; i <= n; i++) | |
printf(" %d", A[i]); | |
printf("\n"); | |
return 0; | |
} |
# 优先队列
#include <iostream> | |
#include <cstdio> | |
#include <algorithm> | |
using namespace std; | |
const int maxx = 2000000; | |
const int INF = 1 << 30; | |
int A[maxx + 1]; | |
int n; | |
void maxHeapify(int i) { | |
int left = 2 * i, right = 2 * i + 1; | |
int largest; | |
// 从左子结点、自身、右子结点选出值最大的结点,然后继续往下递归 | |
if (left <= n && A[left] > A[i]) | |
largest = left; | |
else | |
largest = i; | |
if (right <= n && A[right] > A[largest]) | |
largest = right; | |
if (largest != i) { | |
swap(A[i], A[largest]); | |
maxHeapify(largest); | |
} | |
} | |
int extract() | |
{ | |
int maxv; | |
if (n < 1) | |
return -INF; | |
maxv = A[1]; | |
A[1] = A[n--]; | |
maxHeapify(1); | |
return maxv; | |
} | |
int insert(int key) { | |
n++; | |
int i = n; | |
A[n] = -INF; | |
if (key < A[i]) | |
return -INF; | |
A[i] = key; | |
while (i > 1 && A[i / 2] < A[i]) { | |
swap(A[i], A[i / 2]); | |
i /= 2; | |
} | |
} | |
int main() | |
{ | |
char op[20]; | |
int k; | |
while (scanf("%s", op) != EOF&&op[2] != 'd') { | |
if (op[0] == 'i') { | |
scanf("%d", &k); | |
insert(k); | |
} | |
else { | |
printf("%d\n", extract()); | |
} | |
} | |
return 0; | |
} |
# 动态规划
# 斐波那契
#include <iostream> | |
#include <cstdio> | |
using namespace std; | |
int main() | |
{ | |
int F[45],n; | |
F[0] = F[1] = 1; | |
for (int i = 2; i <= 44; i++) | |
F[i] = F[i - 1] + F[i - 2]; | |
scanf("%d", &n); | |
printf("%d\n", F[n]); | |
return 0; | |
} |
# 最长公共子序列
#include <iostream> | |
#include <cstdio> | |
#include <cstring> | |
#include <algorithm> | |
using namespace std; | |
const int maxx = 1010; | |
int c[maxx][maxx]; | |
int lcs(char s1[],char s2[]) { | |
int m = strlen(s1), n = strlen(s2); | |
for (int i = 1; i <= m; i++) | |
c[i][0] = 0; | |
for (int i = 1; i <= n; i++) | |
c[0][i] = 0; | |
for (int i = 0; i < m; i++) { | |
for (int j = 0; j < n; j++) { | |
if (s1[i] == s2[j]) | |
c[i+1][j+1] = c[i][j] + 1; | |
else | |
c[i+1][j+1] = max(c[i][j+1], c[i + 1][j]); | |
} | |
} | |
return c[m][n]; | |
} | |
int main() | |
{ | |
char s1[maxx], s2[maxx]; | |
int t; | |
scanf("%d", &t); | |
for (int i = 0; i < t; i++) { | |
scanf("%s %s", s1, s2); | |
printf("%d\n",lcs(s1,s2)); | |
} | |
return 0; | |
} |
# 矩阵连乘
#include <iostream> | |
#include <cstdio> | |
#include <cstring> | |
#include <algorithm> | |
using namespace std; | |
const int maxx = 110; | |
const int INF = 1 << 30; | |
int main() | |
{ | |
int n, p[maxx], m[maxx][maxx]; | |
scanf("%d", &n); | |
for (int i = 1; i <= n; i++) | |
scanf("%d %d", &p[i - 1], &p[i]); | |
for (int i = 1; i <= n; i++) | |
m[i][i] = 0; | |
for (int l = 2; l <= n; l++) { | |
for (int i = 1; i <= n - l + 1; i++) { | |
int j = i + l - 1; | |
m[i][j] = INF; | |
for (int k = i; k <= j - 1; k++) | |
m[i][j] = min(m[i][j], m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]); | |
} | |
} | |
printf("%d\n", m[1][n]); | |
return 0; | |
} |
# 图
# 图的表示
#include <iostream> | |
#include <cstdio> | |
#include <cstring> | |
using namespace std; | |
const int maxx = 110; | |
int main() | |
{ | |
int n, m[maxx][maxx]; | |
int u, num, v; | |
scanf("%d", &n); | |
memset(m, 0, sizeof(m)); | |
for (int i = 1; i <= n; i++) { | |
scanf("%d %d", &u, &num); | |
for (int j = 1; j <= num; j++) { | |
scanf("%d", &v); | |
m[u][v] = 1; | |
} | |
} | |
for (int i = 1; i <= n; i++) | |
for (int j = 1; j <= n; j++) | |
printf("%d%c", m[i][j], j == n ? '\n' : ' '); | |
return 0; | |
} |
# DFS
#include <iostream> | |
#include <cstdio> | |
#include <cstring> | |
#include <stack> | |
using namespace std; | |
const int maxx = 110; | |
int n, m[maxx][maxx]; | |
int u, num, v; | |
int d[maxx], f[maxx]; | |
int flag[maxx]; | |
int nowtime = 1; | |
void dfs(int u) { | |
// 入栈时间 | |
flag[u] = 1; | |
d[u] = nowtime++; | |
for (int i = 1; i <= n; i++) { | |
if (flag[i] == 0 && m[u][i] == 1) { | |
dfs(i); | |
} | |
} | |
// 出栈时间 | |
f[u] = nowtime++; | |
} | |
int main() | |
{ | |
scanf("%d", &n); | |
memset(m, 0, sizeof(m)); | |
memset(f, 0, sizeof(f)); | |
for (int i = 1; i <= n; i++) { | |
scanf("%d %d", &u, &num); | |
for (int j = 1; j <= num; j++) { | |
scanf("%d", &v); | |
m[u][v] = 1; | |
} | |
} | |
for (int i = 1; i <= n; i++) { | |
if(flag[i] == 0) | |
dfs(i); | |
} | |
for (int i = 1; i <= n; i++) { | |
printf("%d %d %d\n", i, d[i], f[i]); | |
} | |
return 0; | |
} |
# BFS
#include <iostream> | |
#include <cstdio> | |
#include <cstring> | |
#include <queue> | |
using namespace std; | |
const int maxx = 110; | |
int n, m[maxx][maxx]; | |
int u, num, v; | |
int flag[maxx]; | |
int d[maxx]; | |
void bfs() { | |
queue<int>q; | |
q.push(1); | |
d[1] = 0; | |
while (!q.empty()) { | |
int u = q.front(); | |
q.pop(); | |
for (int i = 2; i <= n; i++) { | |
if (m[u][i] == 1 && flag[i] == 0) { | |
// 标记为已经访问 | |
flag[i] = 1; | |
// 更新长度 | |
d[i] = d[u] + 1; | |
// 压入栈内 | |
q.push(i); | |
} | |
} | |
} | |
} | |
int main() | |
{ | |
scanf("%d", &n); | |
memset(m, 0, sizeof(m)); | |
for (int i = 1; i <= n; i++) { | |
scanf("%d %d", &u, &num); | |
// 初始化 | |
flag[i] = 0; | |
d[i] = -1; | |
for (int j = 1; j <= num; j++) { | |
scanf("%d", &v); | |
m[u][v] = 1; | |
} | |
} | |
bfs(); | |
for (int i = 1; i <= n; i++) { | |
printf("%d %d\n", i, d[i]); | |
} | |
return 0; | |
} |
# 连通分量
#include <iostream> | |
#include <cstdio> | |
#include <cstring> | |
#include <stack> | |
#include <vector> | |
using namespace std; | |
const int maxx = 100010; | |
int n, m; | |
int u, num, v; | |
int flag[maxx]; | |
int color[maxx]; | |
vector<int> G[maxx]; | |
int c = 1; | |
void dfs(int t) { | |
stack<int>s; | |
s.push(t); | |
color[t] = c; | |
while (!s.empty()) { | |
int u = s.top(); s.pop(); | |
int len = G[u].size(); | |
for (int i = 0; i < len; i++) { | |
int v = G[u][i]; | |
if (flag[v] == 0) { | |
color[v] = c; | |
flag[v] = 1; | |
s.push(v); | |
} | |
} | |
} | |
} | |
int main() | |
{ | |
int q; | |
memset(flag, 0, sizeof(flag)); | |
scanf("%d %d", &n, &m); | |
for (int i = 0; i < m; i++) { | |
scanf("%d %d", &u, &v); | |
// 将顶点 v 添加到 G [u] 数组中 | |
G[u].push_back(v); | |
G[v].push_back(u); | |
} | |
for (int i = 0; i < n; i++) { | |
if (flag[i] == 0) { | |
dfs(i); | |
c++; | |
} | |
} | |
scanf("%d", &q); | |
for (int i = 0; i < q; i++) { | |
scanf("%d %d", &u, &v); | |
if (color[u] == color[v]) { | |
printf("yes\n"); | |
} | |
else { | |
printf("no\n"); | |
} | |
} | |
return 0; | |
} |