《机试指南》

一、输入格式

1.1单组输入

#include<iostream>
using namespace std;
int main()
{
    int a, b;
    cin >> a >> b;
    cout << a + b << endl;
    return 0;
}

1.2多组输入,未知组数

#include<iostream>
using namespace std;
int main()
{
    int a, b;
    while(cin >> a >> b) 
    {
        cout << a + b << endl;
    }
    return 0;
}

1.3多组输入,已知组数

#include<iostream>
using namespace std;
int main()
{
    int n; // 指定组数
    cin >> n;
    while(n--)
    {
        int a, b;
        cin >> a >> b;
        cout << a+b << endl;
    }
    return 0;
}

1.4多组输入,指定跳出

#include<iostream>
using namespace std;
int main()
{
    int a, b;
    while(cin >> a >> b)
    {
        if(a == 0 && b == 0) //指定条件,输入0,0时跳出循环
        {
            break;
        }
        cout << a+b << endl;
    }
    return 0;
}

二、暴力求解

2.1枚举

2.1.1 abc
#include<iostream>
using namespace std;
int main()
{
    //abc+bcc=532
    //问题等价为100a+10b+c+100b+10c+c=100a+110b+12c=532
    //枚举三个数字,判断是否符合条件
    for(int a = 0; a < 10; a++)
    {
        for(int b = 0; b < 10; b++)
        {
            for(int c = 0; c < 10; c++)
            {
                if(100 * a + 110 * b + 12 * c == 532)
                {
                    cout<<a<<" "<<b<<" "<<c<<endl;
                }
            }
        }
    }
}
2.1.2 反序数
#include<iostream>
using namespace std;
int getReverse(int number)
{
    //求number的反序数,如1234的反序数为4321
    //定义反序数,该数初始为0
    int reverseNumber = 0;
    while(number != 0)
    {
        reverseNumber *= 10;
        reverseNumber += number % 10;
        number /= 10;
    }
    return reverseNumber;
}
int main()
{
    for (int i = 1000; i < 10000; i++)
    {
        if (getReverse(i) == i * 9)
        {
            cout<<i<<endl;
        }
    }
}

2.2模拟

2.2.1 输出梯形
#include<iostream>
using namespace std;
int main()
{
    int h; //梯形的高度
    cin >> h;
    //梯形的第一行有h个*,第h行有h+2(h-1)个*,每行比上一行多两个*
    //对于梯形的第i行,该行有h+2(i-1)个*,有h+2(h-1)-[h+2(i-1)]=2(h-i)个空格
    for(int i = 0; i < h; i++){
        for(int j = 0; j < h+2*(h-1); j++){
            if(j < 2*(h-i-1)){
                cout<<" ";
            }
            else{
                cout<<"*";
            }
        }
        cout<<endl;
    }
    return 0;
}
2.2.2 叠筐
2.2.3 今年的第几天?
#include<iostream>
using namespace std;
int dayTable[2][12] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//平年
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//闰年
};
bool isLeapYear(int year){
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main(){
    int year, month, day;
    while(cin>>year>>month>>day){
        int row = isLeapYear(year);
        int n = 0;
        for(int i = 0; i < month-1; i++){
            n += dayTable[row][i];
        }
        n += day;
        cout<<n<<endl;
    }
    return 0;
}
2.2.4 打印日期
#include<iostream>
#include<iomanip>
using namespace std;
int dayTable[2][12] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//平年
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},//闰年
};
bool isLeapYear(int year){
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main(){
    int year, n;
    while(cin>>year>>n){
        int row = isLeapYear(year);
        int month = 0;
        while(n > dayTable[row][month]){
            n -= dayTable[row][month];
            month++;
        }
        month++;
        cout<<year<<"-"<<setfill('0')<<setw(2)<<month<<"-"<<setfill('0')<<setw(2)<<n<<endl;
    }
    return 0;
}
2.2.5 手机键盘
#include<iostream>
#include<iomanip>
using namespace std;
//记录各个字母需要按键的次数
int keyTable[26] = {1, 2, 3, //abc
                    1, 2, 3, //def
                    1, 2, 3, //ghi
                    1, 2, 3, //jkl
                    1, 2, 3, //mno
                    1, 2, 3, 4,//pqrs
                    1, 2, 3, //tuv
                    1, 2, 3, 4 //wxyz
                    };
int main(){
    string str;
    while(cin>>str){
        int n = 0;
        for(int i = 0; i < str.length(); i++){
            n += keyTable[str[i]-'a'];
            //判断连续的两个字母是否在同一按键上
            if(i != 0 && str[i] - str[i-1] == keyTable[str[i]-'a'] - keyTable[str[i-1]-'a']){
                n += 2;
            }
        }
        cout<<n<<endl;
    }
    return 0;
}

三、排序

3.1 基础排序

3.1.1 成绩排名
#include<iostream>
#include<algorithm>
using namespace std;
struct Student{
    int number;
    int score;
};
bool compare(Student s1, Student s2){
    if (s1.score == s2.score){
        return s1.number < s2.number;
    } else {
        return s1.score < s2.score;
    }
}
int main(){
    int n;
    cin>>n;
    Student students[n];
    for(int i = 0; i < n; i++){
        int num, sre;
        cin>>num>>sre;
        students[i].number = num;
        students[i].score = sre;
    }
    sort(students, students + n, compare);
    for(int i = 0; i < n; i++){
        cout<<students[i].number<<" "<<students[i].score<<endl;
    }
    return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
struct Student{
    int number;
    int score;
    bool operator< (Student student) const{
        if(score == student.score){
            return number < student.number;
        } else {
            return score < student.score;
        }
    }
};
int main(){
    int n;
    cin>>n;
    Student students[n];
    for(int i = 0; i < n; i++){
        int num, sre;
        cin>>num>>sre;
        students[i].number = num;
        students[i].score = sre;
    }
    sort(students, students + n);
    for(int i = 0; i < n; i++){
        cout<<students[i].number<<" "<<students[i].score<<endl;
    }
    return 0;
}
3.1.2 整数奇偶排序
#include<iostream>
#include<algorithm>
using namespace std;
int arr[10];
bool compare(int x, int y){
    //输入10个整数,彼此以空格分隔。重新排序以后输出(也按空格分隔),要求:
    //1.先输出其中的奇数,并按从大到小排列;
    //2.然后输出其中的偶数,并按从小到大排列。
    if(x % 2 == 1 && y % 2 == 1){
        //x和y都是奇数,从大到小排序
        return x > y;
    } else if (x % 2 == 0 && y % 2 == 0){
        //x和y都是偶数,从小到大排序
        return y > x;
    } else {
        //x和y一个是奇数,另一个是偶数,先输出奇数
        return x % 2 > y % 2;
        //若x是奇数,返回true;若y是奇数,返回false
    }
}
int main(){
    while(cin>>arr[0]){
        for(int i = 1; i < 10; i++){
            cin>>arr[i];
        }
        sort(arr, arr + 10, compare);
        for(int i = 0; i < 10; i++){
            cout<<arr[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

3.2 扩展排序

3.2.1 sort(计数排序)
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1e6 + 10;
const int RANGE = 5e5;
int arr[MAXN];
int number[MAXN];
int main(){
    int n,m;//n为输入元素的个数,m为输出元素的个数
    while(cin>>n>>m){
        memset(number, 0, sizeof(number));//清空辅助数组
        for(int i = 0; i < n; i++){
            cin>>arr[i];
            //arr[i]的范围为(-5e5,5e5)
            number[arr[i] + RANGE]++;
        }
        int index = 0;//重新赋值arr数组,保留number非0的元素
        for(int i = 0; i < MAXN; i++){
            while(number[i]--){
                arr[index++] = i - RANGE;
            }
        }
        for(int i = n-1; i >= n-m; i--){
            if(i == n-m){
                cout<<arr[i]<<endl;
            } else{
                cout<<arr[i]<<" ";
            }
        }
    }
    return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1e6 + 10;
const int RANGE = 5e5;
int arr[MAXN];
int number[MAXN];
int main(){
    int n,m;//n为输入元素的个数,m为输出元素的个数
    bool flag;
    while(cin>>n>>m){
        memset(number, 0, sizeof(number));//清空辅助数组
        flag = true;
        for(int i = 0; i < n; i++){
            cin>>arr[i];
            //arr[i]的范围为(-5e5,5e5)
            number[arr[i] + RANGE]++;
        }
        for(int i = MAXN; i >=0; i--){
            while(number[i]-- > 0){
                //cout<<number[i]<<endl;
                if(m-- > 1){
                    cout<<i - RANGE<<" ";
                } else {
                    cout<<i - RANGE<<endl;
                    flag = false;
                }
            }
            if (flag == false) {
                break;
            }
        }
    }
    return 0;
}
3.2.2 逆序数

枚举,时间复杂度大

#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1e5 + 10;
int arr[MAXN];
int main(){
    int n;
    while (cin>>n) {
        long long answer = 0;
        memset(arr, 0, sizeof(arr));
        for (int i = 0; i < n; i++) {
            cin>>arr[i];
        }
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                if (arr[i] > arr[j]) {
                    answer++;
                }
            }
        }
        cout<<answer<<endl;
    }
    return 0;
}

利用归并排序

#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1000 + 10;
int arr[MAXN];
int temp[MAXN];
int number;
void Combine(int left, int middle, int right){
    int i = left;
    int j = middle + 1;
    int k = left;
    while(i <= middle && j <= right){
        if (arr[i] <= arr[j]) {
            temp[k++] = arr[i++];
        } else {
            //前面的数大于后面的数,形成逆序对
            number += middle + 1 - i;
            temp[k++] = arr[j++];
        }
    }
    while(i <= middle) {
        temp[k++] = arr[i++];
    }
    while(j <= right) {
        temp[k++] = arr[j++];
    }
    for(k = left; k <= right; k++){
        arr[k] = temp[k];
    }
}
void MergeSort(int left, int right){
    if(left < right){
        int middle = left + (right - left) / 2;
        MergeSort(left, middle);
        MergeSort(middle + 1, right);
        Combine(left, middle, right);
    }
}
int main(){
    int n;
    cin>>n;
    for(int i = 0; i < n; i++){
        cin>>arr[i];
    }
    number = 0;
    MergeSort(0, n-1);
    cout<<number;
    return 0;
}
3.2.3 寻找第k大元素
快速排序
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN = 1000 + 10;
int arr[MAXN];
int Partition(int left, int right){
    //选择随机的基准元素
    int random = left + rand() % (right - left + 1);
    //将基准元素与第一个元素交换位置
    swap(arr[left], arr[random]);
    while(left < right){
        //从右到左依次对比,直到右指针所指的元素小于左指针所指的元素
        while(left < right && arr[left] <= arr[right]){
            right--;
        }
        //此时,右指针所指的元素小于左指针所指的元素,交换两个指针
        swap(arr[left], arr[right]);
        //从左到右依次对比,直到左指针所指的元素大于右指针所指的元素
        while(left < right && arr[left] <= arr[right]){
            left++;
        }
        此时,左指针所指的元素大于右指针所指的元素,交换两个指针
        swap(arr[left], arr[right]);
    }
    return left;
}
int QuickSort(int left, int right, int p){
    if(left < right){
        //获取随机选择的基准元素的位置
        int position = Partition(left, right);
        //如果该元素的位置小于第k大元素所在的位置,在该元素的右边继续查找
        //如果该元素的位置大于第k大元素所在的位置,在该元素的右边继续查找
        //如果该元素的位置正是需要寻找的第k大元素的位置,返回这个位置上的值
        if(position < p){
            QuickSort(position + 1, right, p);
        } else if (position > p){
            QuickSort(left, position - 1, p);
        } else {
            return arr[position];
        }
    }
}
int main(){
    int n;
    cin>>n;
    for(int i = 0; i < n; i++){
        cin>>arr[i];
    }
    int k;
    cin>>k;
    int answer = QuickSort(0, n-1, n-k);
    cout<<answer;
    return 0;
}
优先队列
#include<iostream>
#include<queue>
using namespace std;
priority_queue<int> arr;
int main(){
    while (getchar() != ']') {
        int number;
        cin>>number;
        arr.push(number);
    }
    int i = 1;
    while (i < 3) {
        arr.pop();
        i++;
    }
    cout<<arr.top();
    return 0;
}

3.3 基础查找

3.3.1 线性查找
#include<iostream>
using namespace std;
const int MAXN = 100 + 10;
int arr[MAXN];
bool LinearSearch(int n, int target){
    for(int i = 0; i < n; i++){
        if(arr[i] == target){
            return true;
        }
    }
    return false;
}
int main(){
    //先指定数组长度
    int n;
    cin>>n;
    //初始化数组
    for(int i = 0; i < n; i++){
        cin>>arr[i];
    }
    //输入待查找元素的个数
    int m;
    cin>>m;
    while(m--){
        int target;
        cin>>target;
        if(LinearSearch(n, target)){
            cout<<"YES"<<endl;
        } else {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}
3.3.2 二分查找
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
int arr[MAXN];
bool BinarySearch(int n, int target){
    int left = 0;
    int right = n - 1;
    while(left <= right){
        int middle = left + (right - left) / 2;
        if (target == arr[middle]){
            //已查找到目标元素
            return true;
        } else if(target < arr[middle]){
            //在中间元素的左边查找
            right = middle - 1;
        } else {
            //在中间元素的右边查找
            left = middle + 1;
        }
    }
    return false;
}
int main(){
    //先指定数组长度
    int n;
    cin>>n;
    //初始化数组
    for(int i = 0; i < n; i++){
        cin>>arr[i];
    }
    //输入待查找元素的个数
    int m;
    cin>>m;
    while(m--){
        int target;
        cin>>target;
        sort(arr, arr + n);
        if(BinarySearch(n, target)){
            cout<<"YES"<<endl;
        } else {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
int arr[MAXN];
int main(){
    //先指定数组长度
    int n;
    cin>>n;
    //初始化数组
    for(int i = 0; i < n; i++){
        cin>>arr[i];
    }
    //输入待查找元素的个数
    int m;
    cin>>m;
    while(m--){
        int target;
        cin>>target;
        //lower_bound返回大于或等于目标值的第一个位置(指针)
        //upper_bound返回大于目标值的第一个位置(指针)
        sort(arr, arr + n);
        int position = lower_bound(arr, arr + n, target) - arr;
        if(position != n && arr[position] == target){
            cout<<"YES"<<endl;
        } else {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}
3.3.3 散列查找
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
const int RANGE = 1e6 + 10;
int arr[MAXN];
bool hashTable[RANGE];
int main(){
    //先指定数组长度
    int n;
    cin>>n;
    //初始化数组
    for(int i = 0; i < n; i++){
        cin>>arr[i];
        hashTable[arr[i]] = true;
    }
    //输入待查找元素的个数
    int m;
    cin>>m;
    while(m--){
        int target;
        cin>>target;
        if(hashTable[target]){
            cout<<"YES"<<endl;
        } else {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}
#include<iostream>
#include<unordered_map>
using namespace std;
const int MAXN = 100 + 10;
const int RANGE = 1e6 + 10;
int arr[MAXN];
unordered_map<int, bool> hashTable;
int main(){
    //先指定数组长度
    int n;
    cin>>n;
    //初始化数组
    for(int i = 0; i < n; i++){
        cin>>arr[i];
        hashTable[arr[i]] = true;
    }
    //输入待查找元素的个数
    int m;
    cin>>m;
    while(m--){
        int target;
        cin>>target;
        if(hashTable[target]){
            cout<<"YES"<<endl;
        } else {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

四、字符串

4.1 字符串操作

4.1.1 特殊乘法(遍历)
#include<iostream>
#include<string>
using namespace std;
int main(){
    string str1, str2;
    while(cin >> str1 >> str2){
        int answer = 0;
        for(int i = 0; i < str1.size(); i++){
            for(int j = 0; j < str2.size(); j++){
                answer += (str1[i] - '0') * (str2[j] - '0');
            }
        }
        cout<<answer<<endl;
    }
    return 0;
}
4.1.2 简单密码(加密)
#include<iostream>
#include<string>
using namespace std;
int main(){
    string str;
    while(getline(cin, str)){
        //如果输入的第一行为ENDOFINPUT则跳出循环
        if(str == "ENDOFINPUT"){
            break;
        }
        //输入待加密字符串
        getline(cin, str);
        for(int i = 0; i < str.size(); i++){
            //对大写字母进行加密
            if(str[i] >= 'A' && str[i] <= 'Z'){
                //str[i] - 'A'得到大写字母在字母表中的位置
                //(str[i] - 'A' - 5 + 26)%26得到加密后的字母在字母表的位置
                //str[i] = (str[i] - 'A' - 5 + 26) % 26 + 'A'得到加密后的字母
                str[i] = (str[i] - 'A' - 5 + 26) % 26 + 'A';
            }
        }
        cout<<str<<endl;
        getline(cin, str);
    }
    return 0;
}
4.1.3 统计字符(统计)
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int MAXN = 128;
int number[MAXN];
int main(){
    string str1, str2;
    while(getline(cin, str1)){
        if(str1 == "#"){
            break;
        }
        memset(number, 0, sizeof(number));
        //输入str2,统计str2中各个字符出现的次数
        getline(cin, str2);
        for(int i = 0; i < str2.size(); i++){
            //数组以字符为下标,实质就是用该字符的ASCII码作为下标
            number[str2[i]]++;
        }
        for(int i = 0; i < str1.size(); i++){
            cout<<str1[i]<<" "<<number[str1[i]]<<endl;
        }
    }
    return 0;
}

4.2 字符串匹配

五、线性数据结构

5.1 向量

5.2 队列

5.2.1 猫狗收养所
#include<iostream>
#include<queue>
using namespace std;
struct Animal{
    int number;//动物编号
    int order;//动物进入收容所的次序
    Animal(int n, int o) : number(n), order(o) {}
};
int main(){
    queue<Animal> dogs;
    queue<Animal> cats;
    int n;//操作序列的次数
    cin>>n;
    int order = 0;//记录次序
    for (int i = 0; i < n; i++){
        int event;//event=1:有动物进入收容所,并定义编号;event=2,有人收养动物,并指明方法
        cin>>event;
        if(event == 1){
            //收容动物,正数代表狗,负数代表猫
            int number;
            cin>>number;
            if(number > 0){
                dogs.push(Animal(number, order++));
            } else if (number < 0){
                cats.push(Animal(number, order++));
            }
        } else if (event == 2){
            //收养动物,并指明方法
            //way=0:收养第一个动物
            //way=1:收养第一只狗
            //way=-1;收养第一只猫
            int way;
            cin>>way;
            if (way == 0 && !dogs.empty() && !cats.empty()){
                if (dogs.front().order < cats.front().order){
                    cout<<dogs.front().number<<" ";
                    dogs.pop();
                } else {
                    cout<<cats.front().number<<" ";
                    cats.pop();
                }
            } else if (way == 0 && !dogs.empty() && cats.empty()){
                cout<<dogs.front().number<<" ";
                dogs.pop();
            } else if (way == 0 && !cats.empty() && dogs.empty()){
                cout<<cats.front().number<<" ";
                cats.pop();
            } else if (way == 1 && !dogs.empty()){
                cout<<dogs.front().number<<" ";
                dogs.pop();
            } else if (way == -1 && !cats.empty()){
                cout<<cats.front().number<<" ";
                cats.pop();
            }
        }
    }
    return 0;
}

5.3 栈

5.3.1 逆序输出
#include<iostream>
#include<stack>
using namespace std;
int main(){
    stack<int> sequence;
    int n;//输入元素的个数
    while(cin>>n){
        for(int i = 0; i < n; i++){
            long long number;
            cin>>number;
            sequence.push(number);
        }
        while(!sequence.empty()){
            cout<<sequence.top()<<" ";
            sequence.pop();
        }
        cout<<endl;
    }
    return 0;
}
5.3.2 括号匹配
#include<iostream>
#include<stack>
using namespace std;
int main(){
    /*
        括号匹配
        给定一个字符串,判断该字符串中的括号是否可以匹配
        如果左括号不匹配,在相应的位置输出?,右括号不匹配,在相应的位置输出#
        其他位置输出空格
    */
    string input, output;
    stack<int> brackets;
    cin>>input;
    output = string(input.size(), ' ');
    int index = 0;
    while(index < input.size()){
        if(input[index] == '('){
            //左括号入栈
            brackets.push(index);
            index++;
        } else if(input[index] == ')'){
            //如果栈中有元素,则匹配,否则说明该右括号无法匹配,输出#
            if (!brackets.empty()){
                brackets.pop();
                index++;
            } else {
                output[index] = '#';
                index++;
            }
        } else{
            //遇到字符,不做任何处理
            index++;
        }
    }
    //扫描一遍字符串后,如果栈非空,说明存在未匹配的左括号
    while(!brackets.empty()){
        output[brackets.top()] = '?';
        brackets.pop();
    }
    cout<<output<<endl;
    return 0;
}
5.3.3 简单计算器(表达式求值)
#include<iostream>
#include<stack>
using namespace std;
stack<double> numbers;
stack<char> operations;
double getNumber(string str, int &index) {
    double number = 0;
    while (isdigit(str[index])) {
        number *= 10;
        number += str[index] - '0';
        index++;
    }
    return number;
}
int priority(char op) {
    if (op == '#') {
        return 0;
    } else if (op == '$') {
        return 1;
    } else if (op == '+' || op == '-') {
        return 2;
    } else {
        return 3;
    }
}
double compute(double x, char op, double y) {
    if (op == '+') {
        return x + y;
    } else if (op == '-') {
        return x - y;
    } else if (op == '*') {
        return x * y;
    } else {
        return x / y;
    }
}
int main(){
    string str;
    while (getline(cin, str)) {
        if (str == "0") {
            break;
        }
        operations.push('#');
        str += '$';
        int i = 0;
        while (i < str.length()) {
            //数字进入数字栈
            if (str[i] == ' ') {
                i++;
            } else if (isdigit(str[i])) {
                double number = getNumber(str, i);
                numbers.push(number);
            } else {
                if (priority(str[i]) > priority(operations.top())) {
                    operations.push(str[i]);
                    i++;
                } else {
                    double y = numbers.top();
                    numbers.pop();
                    double x = numbers.top();
                    numbers.pop();
                    char op = operations.top();
                    operations.pop();
                    //answer += compute(x, op, y);
                    numbers.push(compute(x, op, y));
                }
            }
        }
        cout.precision(2);
        cout.setf(ios::fixed);
        cout<<numbers.top()<<endl;
    }
    return 0;
}

六、 数学问题

6.1 进制转换

6.1.1 10进制转换为N进制
#include<iostream>
#include<stack>
using namespace std;
char Int2Char(int target){
    if (target < 10) {
        //如果数字小于10,则转换为相应的字符
        return target + '0';
    } else {
        //如果数字大于10,则转换为相应的大写字母,如10->A
        return target - 10 + 'A';
    }
}
void ConvertT2N(int number, int n){
    //将10进制转换为N进制
    stack<char> answer;
    if (number == 0) {
        //如果number = 0,直接输出0
        cout<<'0'<<endl;
    } else if (number < 0) {
        number *= -1;
        while (number != 0) {
            answer.push(Int2Char(number % n));
            number /= n;
        }
        answer.push('-');
    } else {
        while (number != 0) {
            answer.push(Int2Char(number % n));
            number /= n;
        }
    }
    //输出转换结果
    while(!answer.empty()){
        cout<<answer.top();
        answer.pop();
    }
    cout<<endl;
}
int main(){
    int number, n;
    cin>>number>>n;
    ConvertT2N(number, n);
    return 0;
}
6.1.2 M进制转换为10进制
#include<iostream>
#include<string>
using namespace std;
int Char2Int(char c){
    if (c >= '0' && c <= '9'){
        return c - '0';
    } else {
        return c - 'A' + 10;
    }
}
void ConvertM2T(string str, int m){
    int number = 0;
    for(int i = 0; i < str.size(); i++){
        number *= m;
        number += Char2Int(str[i]);
    }
    cout<<number<<endl;
}
int main(){
    string str;
    int m;
    cin>>str>>m;
    ConvertM2T(str, m);
    return 0;
}
6.1.3 M进制转换为N进制
#include<iostream>
#include<string>
#include<stack>
using namespace std;
int Char2Int(char c){
    if (c >= '0' && c <= '9'){
        return c - '0';
    } else {
        return c - 'A' + 10;
    }
}
char Int2Char(int target){
    if (target < 10){
        return target + '0';
    } else {
        return target - 10 + 'A';
    }
}
long long ConvertM2T(string str, int m){
    long long number = 0;
    for(int i = 0; i < str.size(); i++){
        number *= m;
        number += Char2Int(str[i]);
    }
    return number;
}
void ConvertT2N(long long number, int n){
    stack<char> answer;
    if (number == 0) {
        cout<<'0'<<endl;
    } else {
        while (number != 0) {
            answer.push(Int2Char(number % n));
            number /= n;
        }
    }
    while (!answer.empty()){
        cout<<answer.top();
        answer.pop();
    }
    cout<<endl;
}
int main(){
    string str;
    int m, n;//输入M进制,输出N进制
    cin>>m>>n;
    cin>>str;
    long long number = ConvertM2T(str, m);//M进制转换为10进制
    //cout<<number;
    ConvertT2N(number, n);//10进制转换为N进制
    return 0;
}

6.2 最大公约数和最小公倍数

6.2.1 最大公约数
递归
#include<iostream>
using namespace std;
int GCD(int a, int b){
    if (b == 0) {
        //递归边界
        return a;
    } else {
        return GCD(b, a % b);
    }
}
int main(){
    int a, b;
    while(cin>>a>>b){
        cout<<GCD(a, b)<<endl;
    }
    return 0;
}
循环
#include<iostream>
using namespace std;
int getAnswer(int x, int y) {
    while (x % y != 0) {
        int z = x % y;
        x = y;
        y = z;
    }
    return y;
}
int main(){
    int x, y;
    while (cin>>x>>y) {
        cout<<getAnswer(x, y)<<endl;
    }
    return 0;
}
6.2.2 最小公倍数

LCM(a, b) = (a * b) / GCD(a, b)

#include<iostream>
using namespace std;
int GCD(int a, int b){
    if (b == 0) {
        //递归边界
        return a;
    } else {
        return GCD(b, a % b);
    }
}
int main(){
    int a, b;
    while(cin>>a>>b){
        cout<<(a * b) / GCD(a, b)<<endl;
    }
    return 0;
}

6.3 质数

6.3.1 质数判别
#include<iostream>
#include<cmath>
using namespace std;
bool isPrimeNumber(int a) {
    if (a < 2){
        return false;
    } else {
        for (int i = 2; i <= pow(a, 0.5); i++) {
            if (a % i == 0){
                return false;
            }
        }
    }
    return true;
}
int main(){
    int a;
    while(cin>>a){
        if (isPrimeNumber(a)) {
            cout<<"yes"<<endl;
        } else {
            cout<<"no"<<endl;
        }
    }
    return 0;
}
6.3.2 第k个质数
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 1e5 + 10;
vector<int> prime;
bool isPrime[MAXN];
void Initial() {
    fill(isPrime, isPrime + MAXN, true);
    isPrime[0] = false;
    isPrime[1] = false;
    for (int i = 2; i < MAXN; i++) {
        if (!isPrime[i]) {
            continue;
        } else {
            prime.push_back(i);
            for (int j = i * 2; j < MAXN; j += i) {
                isPrime[j] = false;
            }
        }
    }
}
int main(){
    Initial();
    int k;
    while(cin>>k){
        cout<<prime[k-1]<<endl;
    }
    return 0;
}
6.3.3 质因数的个数
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 4e4;
vector<int> prime;
bool isPrime[MAXN];
void Initial() {
    fill(isPrime, isPrime + MAXN, true);
    isPrime[0] = false;
    isPrime[1] = false;
    for (int i = 2; i < MAXN; i++) {
        if (!isPrime[i]) {
            continue;
        } else {
            prime.push_back(i);
            for (int j = i * 2; j < MAXN; j += i) {
                isPrime[j] = false;
            }
        }
    }
}
int getAnswer(int n) {
    int answer = 0;
    for (int i = 0; i < prime.size(); i++) {
        while (n % prime[i] == 0) {
            //prime[i]为质因数
            answer++;
            n /= prime[i];
        }
    }
    if (n > 1) {
        //该整数有一个大于根号n的质因子
        //如600154635 = 3 * 5 * 40010309
        answer += 1;
    }
    return answer;
}
int main(){
    Initial();
    int k;
    while(cin>>k){
        cout<<getAnswer(k)<<endl;
    }
    return 0;
}
6.3.4 约数个数
#include<iostream>
#include<vector>
using namespace std;
const int MAXN = 4e4;
vector<int> prime;
bool isPrime[MAXN];
void Initial() {
    fill(isPrime, isPrime + MAXN, true);
    isPrime[0] = false;
    isPrime[1] = false;
    for (int i = 2; i < MAXN; i++) {
        if (!isPrime[i]) {
            continue;
        } else {
            prime.push_back(i);
            for (int j = i * 2; j < MAXN; j += i) {
                isPrime[j] = false;
            }
        }
    }
}
int getAnswer(int n) {
    int answer = 1;
    int e[prime.size()];
    fill(e, e + prime.size(), 0);
    for (int i = 0; i < prime.size(); i++) {
        while (n % prime[i] == 0) {
            //prime[i]为质因数
            e[i]++;
            n /= prime[i];
        }
        answer *= e[i] + 1;
    }
    if (n > 1) {
        //该整数有一个大于根号n的质因子
        //如600154635 = 3 * 5 * 40010309
        answer *= 2;
    }
    return answer;
}
int main(){
    Initial();
    int k;
    cin>>k;
    while(k--){
        int n;
        cin>>n;
        cout<<getAnswer(n)<<endl;
    }
    return 0;
}

6.4 快速幂

6.4.1 人见人爱A^B
#include<iostream>
using namespace std;
int QuickPower(int a, int b) {
    int answer = 1;
    /*
        任何一个十进制整数都可以转换为2进制,如29=11101
        所以3^29 = 3^1 * 3^4 * 3^8 * 3^16
        可以通过这种方式求快速幂
    */
    while (b != 0) {
        if(b % 2 == 1) {
            //对应的2进制位为1,则answer*a
            answer *= a;
            answer %= 1000;
        }
        //每次操作之后,b右移一位,a升幂
        b /= 2;
        a *= a;
        a %= 1000;
    }
    return answer;
}
int main(){
    int a, b;
    while (cin>>a>>b) {
        if (a == 0 && b == 0) {
            break;
        }
        cout<<QuickPower(a, b)<<endl;
    }
    return 0;
}

6.5 矩阵

6.5.1 矩阵相加
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
    int row, column;
    int matrix[MAXN][MAXN];
    Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
    for (int i = 0; i < x.row; i++){
        for (int j = 0; j < x.column; j++) {
            cin>>x.matrix[i][j];
        }
    }
}
void outputMatrix(Matrix x){
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < x.column; j++) {
            if (j == 0) {
                cout<<x.matrix[i][j];
            } else {
                cout<<" "<<x.matrix[i][j];
            }
        }
        cout<<endl;
    }
}
Matrix addMatrix(Matrix x, Matrix y) {
    Matrix result = Matrix(x.row, x.column);
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < x.column; j++){
            result.matrix[i][j] = x.matrix[i][j] + y.matrix[i][j];
        }
    }
    return result;
}
int main(){
    Matrix x = Matrix(2, 2);
    Matrix y = Matrix(2, 2);
    inputMatrix(x);
    inputMatrix(y);
    outputMatrix(addMatrix(x, y));
    return 0;
}
6.5.2 矩阵相乘
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
    int row, column;
    int matrix[MAXN][MAXN];
    Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
    for (int i = 0; i < x.row; i++){
        for (int j = 0; j < x.column; j++) {
            cin>>x.matrix[i][j];
        }
    }
}
void outputMatrix(Matrix x){
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < x.column; j++) {
            if (j == 0) {
                cout<<x.matrix[i][j];
            } else {
                cout<<" "<<x.matrix[i][j];
            }
        }
        cout<<endl;
    }
}
Matrix multiplyMatrix(Matrix x, Matrix y) {
    Matrix result = Matrix(x.row, y.column);
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < y.column; j++){
            result.matrix[i][j] = 0;
            for (int k = 0; k < x.column; k++) {
                result.matrix[i][j] += x.matrix[i][k] * y.matrix[k][j];
            }
        }
    }
    return result;
}
int main(){
    Matrix x = Matrix(2, 3);
    Matrix y = Matrix(3, 2);
    inputMatrix(x);
    inputMatrix(y);
    outputMatrix(multiplyMatrix(x, y));
    return 0;
}
6.5.3 矩阵转置
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
    int row, column;
    int matrix[MAXN][MAXN];
    Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
    for (int i = 0; i < x.row; i++){
        for (int j = 0; j < x.column; j++) {
            cin>>x.matrix[i][j];
        }
    }
}
void outputMatrix(Matrix x){
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < x.column; j++) {
            if (j == 0) {
                cout<<x.matrix[i][j];
            } else {
                cout<<" "<<x.matrix[i][j];
            }
        }
        cout<<endl;
    }
}
Matrix transMatrix(Matrix x) {
    Matrix result = Matrix(x.column, x.row);
    for (int i = 0; i < x.column; i++) {
        for (int j = 0; j < x.row; j++){
            result.matrix[i][j] = x.matrix[j][i];
        }
    }
    return result;
}
int main(){
    Matrix x = Matrix(2, 3);
    inputMatrix(x);
    outputMatrix(transMatrix(x));
    return 0;
}
6.5.4 矩阵的幂
#include<iostream>
using namespace std;
const int MAXN = 100;
//定义矩阵
struct Matrix{
    int row, column;
    int matrix[MAXN][MAXN];
    Matrix(int r, int c) : row(r), column(c) {}
};
void inputMatrix(Matrix &x){
    for (int i = 0; i < x.row; i++){
        for (int j = 0; j < x.column; j++) {
            cin>>x.matrix[i][j];
        }
    }
}
void outputMatrix(Matrix x){
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < x.column; j++) {
            if (j == 0) {
                cout<<x.matrix[i][j];
            } else {
                cout<<" "<<x.matrix[i][j];
            }
        }
        cout<<endl;
    }
}
Matrix multiplyMaxtrix(Matrix x, Matrix y) {
    Matrix result = Matrix(x.row, y.column);
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < y.column; j++) {
            result.matrix[i][j] = 0;
            for (int k = 0; k < x.column; k++) {
                result.matrix[i][j] += x.matrix[i][k] * y.matrix[k][j];
            }
        }
    }
    return result;
}
Matrix powerMatrix(Matrix x, int k) {
    Matrix result = Matrix(x.row, x.column);
    for (int i = 0; i < x.row; i++) {
        for (int j = 0; j < x.column; j++) {
            if (i == j) {
                result.matrix[i][j] = 1;
            } else {
                result.matrix[i][j] = 0;
            }
        }
    }
    while (k != 0) {
        if (k % 2 == 1) {
            result = multiplyMaxtrix(result, x);
        }
        k /= 2;
        x = multiplyMaxtrix(x, x);
    }
    return result;
}
int main(){
    int n, k;
    while (cin>>n>>k) {
        Matrix x = Matrix(n, n);
        inputMatrix(x);
        outputMatrix(powerMatrix(x, k));
    }
    return 0;
}

6.6 大整数运算

6.6.1 大整数加法
6.6.2 大整数减法
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 10100;
char s1[MAXN], s2[MAXN], s3[MAXN]; //输入的两个数,先以字符串的形式保存
int a[MAXN], b[MAXN], c[MAXN]; //将字符串转换为数字并保持到数组中
bool compare(char str1[], char str2[]) {
    // 判断str1是否大于str2
    if (strlen(str1) != strlen(str2)) {
        return strlen(str1) > strlen(str2);
    }
    for (int i = 0; i < strlen(str1); i++) {
        if (str1[i] != str2[i]) {
            return str1[i] > str2[i];
        }
    }
    return true;
}
int main(){
    cin>>s1>>s2;
    int flag;
    if (!compare(s1, s2)) {
        // s1小于s2,交换
        flag = 1; // 结果为负数
        strcpy(s3, s1);
        strcpy(s1, s2);
        strcpy(s2, s3);
    }
    int la = strlen(s1);
    int lb = strlen(s2);
    int lc = max(la, lb);
    for (int i = 0; i < la; i++) {
        a[la - i] = s1[i] - '0';
    }
    for (int i = 0; i < lb; i++) {
        b[lb - i] = s2[i] - '0';
    }
    for (int i = 1; i <= lc; i++) {
        if (a[i] < b[i]) {
            a[i+1]--;
            a[i] += 10;
        }
        c[i] = a[i] - b[i];
    }
    if (flag == 1) {
        cout<<'-';
    }
    // 前面有多个0,只保留一个
    while (c[lc] == 0 && lc > 1) {
        lc--;
    }
    for (int i = lc; i > 0; i--) {
        cout<<c[i];
    }
    return 0;
}
6.6.3 大整数乘法
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 10100;
char s1[MAXN], s2[MAXN], s3[MAXN]; //输入的两个数,先以字符串的形式保存
int a[MAXN], b[MAXN], c[MAXN]; //将字符串转换为数字并保持到数组中
int main(){
    cin>>s1>>s2;
    int la = strlen(s1);
    int lb = strlen(s2);
    int lc = la + lb;
    for (int i = 0; i < la; i++) {
        a[la - i] = s1[i] - '0';
    }
    for (int i = 0; i < lb; i++) {
        b[lb - i] = s2[i] - '0';
    }
    for (int i = 1; i <= la; i++) {
        for (int j = 1; j <= lb; j++) {
            c[i+j-1] += a[i] * b[j];
        }
    }
    for (int i = 1; i <= lc; i++) {
        if (c[i] > 9) {
            c[i+1] += c[i] / 10;
            c[i] %= 10;
        }
    }
    // 前面有多个0,只保留一个
    while (c[lc] == 0 && lc > 1) {
        lc--;
    }
    for (int i = lc; i > 0; i--) {
        cout<<c[i];
    }
    return 0;
}
6.6.4 大整数除法(高精度除以低精度)
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 5010;
char s[MAXN]; //输入的两个数,先以字符串的形式保存
long long a[MAXN], c[MAXN], x; //将字符串转换为数字并保持到数组中
long long b;
int main(){
    cin>>s>>b;
    long long la = strlen(s);
    for (int i = 1; i <= la; i++) {
        a[i] = s[i-1] - '0';
    }
    for (int i = 1; i <= la; i++) {
        c[i] = (x * 10 + a[i]) / b;
        x = (x * 10 + a[i]) % b;
    }
    long long lc = 1;
    while (c[lc] == 0 && lc < la) {
        lc++;
    }
    for (int i = lc; i <= la; i++) {
        cout<<c[i];
    }
    return 0;
}
6.6.5 大整数除法(高精度除以高精度)
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 300 + 10;
char s1[MAXN], s2[MAXN];
int la, lb, lc;
int a[MAXN], b[MAXN], c[MAXN], temp[MAXN];
int compare(int a[], int b[]) {
    if (a[0] > b[0]) {
        return 1;
    }
    if (a[0] < b[0]) {
        return -1;
    }
    for (int i = a[0]; i > 0; i--) {
        if (a[i] > b[i]) {
            return 1;
        }
        if (a[i] < b[i]) {
            return -1;
        }
    }
    return 0;
}
void copyArr(int b[], int temp[], int k) {
    for (int i = 1; i <= b[0]; i++) {
        temp[i + k] = b[i];
    }
    temp[0] = b[0] + k;
}
void Minus(int a[], int b[]) {
    for (int i = 1; i <= a[0]; i++) {
        if (a[i] < b[i]) {
            a[i + 1]--;
            a[i] += 10;
        }
        a[i] = a[i] - b[i];
    }
    while (a[a[0]] == 0 && a[0] > 1) {
        a[0]--;
    }
}
int main(){
    cin>>s1>>s2;
    a[0] = strlen(s1);
    b[0] = strlen(s2);
    for (int i = 0; i < a[0]; i++) {
        a[a[0] - i] = s1[i] - '0';
    }
    for (int i = 0; i < b[0]; i++) {
        b[b[0] - i] = s2[i] - '0';
    }
    c[0] = a[0] - b[0] + 1;
    for (int i = c[0]; i >= 1; i--) {
        memset(temp, 0, sizeof(temp));
        copyArr(b, temp, i-1);
        while (compare(a, temp) >= 0) {
            c[i]++;
            Minus(a, temp);
        }
    }
    while (c[c[0]] == 0 && c[0] > 0) {
        c[0]--;
    }
    for (int i = c[0]; i > 0; i--) {
        cout<<c[i];
    }
    cout<<endl;
    for (int i = a[0]; i > 0; i--) {
        cout<<a[i];
    }
    return 0;
}

七、贪心策略

7.1 简单贪心

7.1.1 FatMouse's Trade
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1000;
struct change{
    double javabean;
    double food;
};
bool Compare(change x, change y) {
    return x.javabean / x.food > y.javabean / y.food;
}
int main(){
    /*
    老鼠准备了M磅的猫粮,准备和房间里的猫交换咖啡豆,一共有N间房间。
    第i间房间有J[i]磅的咖啡豆,需要F[i]的猫粮交换,老鼠不一定交换一间房间的所有咖啡豆
    它可以用F[i]*a%的猫粮交换J[i]*a%的咖啡豆,求它可以获得最大咖啡豆的数量
    */
    /*
    F[i]的猫粮可以换J[i]的咖啡豆,若使交换的咖啡豆最多,应该尽量使用较少的猫粮交换较多的咖啡豆
    可以利用J[i] / F[i] 计算交换比例,比例最大的为当前最优解
    */
    int m, n;
    while (cin >> m >> n) {
        if (m == -1 && n == -1) {
            break;
        }
        double answer = 0;
        change input[MAXN];
        for (int i = 0; i < n; i++) {
            cin>>input[i].javabean>>input[i].food;
        }
        sort(input, input + n, Compare);
        for (int i = 0; i < n; i++) {
            if (m >= input[i].food) {
                m -= input[i].food;
                answer += input[i].javabean;
            } else {
                answer += (m / input[i].food) * input[i].javabean;
                m = 0;
                break;
            }
        }
        cout.precision(3);
        cout.setf(ios::fixed);
        cout<<answer<<endl;
    }
    return 0;
}
7.1.2 Senior's Gun
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100000+10;
long long guns[MAXN];
long long monsters[MAXN];
bool Compare(long long x, long long y) {
    return x > y;
}
int main(){
    /*
        薛有n把枪,每把枪的攻击力为a[i]
        一天,她遇到了m头怪兽,每头怪兽的防御力为b[j]
        只要满足a[i]>=b[j],薛就可以用枪杀死一头怪兽,并且获得a[i]-b[j]的奖金
        一把枪只能杀死一头怪兽,尝试获得最多奖金。
    */
    /*
        若想获得最多奖金,应该用攻击力最强的枪杀死防御力最低的怪兽
    */
    int t;
    cin>>t;
    while(t--){
        int n, m;
        long long bonus = 0;
        cin>>n>>m;
        //输入n把枪的攻击力
        for (int i = 0; i < n; i++) {
            cin>>guns[i];
        }
        //输入m头怪兽的防御力
        for (int j = 0; j < m; j++) {
            cin>>monsters[j];
        }
        //对枪和怪兽排序,用攻击力最高的枪杀死防御力最低的怪兽
        sort(guns, guns + n, Compare);
        sort(monsters, monsters + m);
        for (int i = 0; i < n; i++) {
            //以下两种情况跳出循环
            //i.当前攻击力最高的枪无法杀死怪兽
            //ii.所有的怪兽都已经被杀死
            if (guns[i] < monsters[i] || i == m) {
                break;
            } else {
                bonus += guns[i] - monsters[i];
            }
        }
        cout<<bonus<<endl;
    }
    return 0;
}
7.1.3 箱子打包
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 10;
int boxes[MAXN];
int main(){
    int n;//物品个数
    int length;//箱子长度
    cin>>n;
    cin>>length;
    for (int i = 0; i < n; i++) {
        cin>>boxes[i];
    }
    sort(boxes, boxes + n);
    int shorter = 0;
    int longer = n - 1;
    int number = 0;
    while (shorter <= longer) {
        //如果长度最小的物品和长度最大的物品可以装入箱子中,则同时装入这两个物品
        //否则,只装入长度最大的物品
        if (boxes[shorter] + boxes[longer] <= length) {
            shorter++;
            longer--;
        } else {
            longer--;
        }
        number++;
    }
    cout<<number<<endl;
    return 0;
}
7.1.4 aggressive cow

题目要求求出任意两个隔间最大的最小距离,可以使用二分策略:

指定一个距离,该距离为最小距离和最大距离的中间值,如果该距离满足题目中的要求,即任意两个隔间的距离都大于此距离,则说明该距离符合要求,此时要扩大该距离,以求出最大的距离,否则缩小该距离

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 10;
int arr[MAXN];
bool judge(int n, int c, int distance){
    int current = arr[0]; //最近放的牛所在的位置
    int number = 1; //当前已放入牛的数量
    for (int i = 1; i < n; i++) {
        //如果把牛放在当前位置后,与前一个位置的距离大于等于指定的距离,则可以放入
        if (arr[i] - current >= distance) {
            current = arr[i];
            number++;
        }
        //如果已放入的牛的数量等于c,则说明该距离满足要求
        if (number == c) {
            return true;
        }
    }
    return false;
}
int main(){
    //n:barn的数量,c:cow的数量
    int n, c;
    while (cin>>n>>c) {
        for (int i = 0; i < n; i++) {
            cin>>arr[i];
        }
        sort(arr, arr + n);
        int left = 1; //两个barn之间的最小距离
        int right = arr[n-1] - arr[0]; //两个barn之间的最大距离
        while (left <= right) {
            int middle = left + (right - left) / 2;
            if (judge(n, c, middle)) {
                //中间的距离满足要求,尝试将距离扩大
                left = middle + 1;
            } else {
                //中间的距离不满足要求,尝试将距离缩小
                right = middle - 1;
            }
        }
        cout<<right<<endl;
    }
    return 0;
}
7.1.5 Drying
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 1e5 + 10;
int water[MAXN];
bool judge(int n, int k, int time) {
    int sum = 0; //选择时间最长的送入烘干机
    for (int i = 0; i < n; i++) {
        //如果water[i] <= time,说明这件衣服可以在规定时间内自然晒干
        //否则,需要送入烘干机,看是否可以在规定时间内烘干
        if (water[i] > time) {
            //当前衣服的含水量大于time,送入烘干机
            sum += ceil((water[i] - time) * 1.0 / (k - 1));
        }
        if (sum > time) {
            return false;
        }
    }
    return true;
}
int main(){
    int n; //衣服的数量
    cin>>n;
    for (int i = 0; i < n; i++) {
        cin>>water[i]; //每件衣服的含水量
    }
    sort(water, water + n);
    int k; //烘干机一分钟能够减少的含水量
    cin>>k;
    if (k == 1) {
        //烘干机的速度与自然晒干的速度相同
        cout<<water[n-1]<<endl;
    } else {
        //采用二分策略
        int left = 1;
        int right = water[n-1];
        while (left <= right) {
            int middle = left + (right - left) / 2;
            if (judge(n, k, middle)) {
                //当前时间可以烘干所有衣服,尝试减少时间
                right = middle - 1;
            } else {
                //当前时间无法烘干所有衣服,尝试延长时间
                left = middle + 1;
            }
        }
        cout<<left<<endl;
    }
    return 0;
}

7.2 区间贪心

07.2.1 今年暑假不AC
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 100 + 10;
struct Program{
    int starttime;
    int endtime;
};
bool compare(Program a, Program b) {
    return a.endtime < b.endtime;
}
Program programs[MAXN];
int main(){
    int n;
    while (cin>>n) {
        if (n == 0) {
            break;
        }
        int number = 1; //可以观看的节目数量
        for (int i = 0; i < n; i++) {
            cin>>programs[i].starttime>>programs[i].endtime;
        }
        //按照结束时间对每个节目进行排序
        sort(programs, programs + n, compare);
        //最近看完的节目的结束时间
        int current = programs[0].endtime;
        for (int i = 1; i < n; i++) {
            //存在开始时间大于等于current的节目,则观看,并更新current
            if (programs[i].starttime >= current) {
                current = programs[i].endtime;
                number++;
            }
        }
        cout<<number<<endl;
    }
    return 0;
}
7.2.2 Radar Installation
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 1000 + 10;
struct Interval{
    double left; //区间左端
    double right; //区间右端
};
Interval arr[MAXN];
bool Compare(Interval a, Interval b) {
    return a.left < b.left;
}
int main(){
    int n, d; //n是岛屿的数目,d是雷达的探测半径
    int caseNumber = 0;
    while(cin>>n>>d){
        if (n == 0 && d == 0) {
            break;
        }
        bool flag = true;
        for (int i = 0; i < n; i++) {
            int x, y;//岛屿的坐标
            cin>>x>>y;
            if (y > d) {
                //存在某个岛屿,其纵坐标大于雷达探测的半径,该岛屿不在探测范围内
                flag = false;
            } else {
                //若雷达可以探测到该岛屿(x,y),则探测器应该安装在(x-r, x+r)之间,
                //其中r=sqrt(d*d - y*y)
                arr[i].left = x - sqrt(d * d - 1.0 * y * y);
                arr[i].right = x + sqrt(d * d - 1.0 * y * y);
            }
        }
        if (!flag) {
            cout<<"Case "<<++caseNumber<<": "<<"-1"<<endl;
        } else {
            //对安装雷达的区间排序,排序规则为按照区间左端从小到大排序
            sort(arr, arr + n, Compare);
            int radar = 1;
            //最新安装的雷达的位置
            double current = arr[0].right;
            for(int i = 1; i < n; i++) {
                if (arr[i].left > current) {
                    //如果当前区间的左端大于前一个安装区间的右端,说明前一个安装的雷达无法
                    //探测到该位置,需要安装一个新的雷达,并更改current
                    current = arr[i].right;
                    radar++;
                } else {
                    current = min(current, arr[i].right);
                }
            }
            cout<<"Case "<<++caseNumber<<": "<<radar<<endl;
        }
    }
    return 0;
}

八、 递归与分治

8.1 递归

8.1.1 汉诺塔1
8.1.2 全排列
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 10;
bool visited[MAXN]; //记录这个位置上的字母是否已经访问过
char sequence[MAXN]; //将访问过的字母加入字符串中
void getPermutation(string str, int depth){
    if (depth == str.length()) {
        //如果当前depth等于字符串长度,输出已访问的字符
        for (int i = 0; i < str.length(); i++) {
            cout<<sequence[i];
        }
        cout<<endl;
    } else {
        for (int i = 0; i < str.length(); i++) {
            if (!visited[i]) {
                visited[i] = true;
                sequence[depth] = str[i];
                getPermutation(str, depth + 1);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      visited[i] = false;
            }
        }
    }
}
int main(){
    string str;
    while (cin>>str) {
        sort(str.begin(), str.end());
        getPermutation(str, 0);
        cout<<endl;
    }
    return 0;
}

8.2 分治

8.2.1 二叉树
#include<iostream>
using namespace std;
const int MAXN = 1e9 + 10;
int getNodeNumbers(int m, int n) {
    //m为所求结点的子树中包含的结点个数
    //n为二叉树中结点的个数
    if (m > n) {
        return 0;
    } else {
        // 对于结点m,其左孩子和右孩子分别为2m和2m+1
        // 求以结点m为根结点的子树的结点的个数,可以转化为求以其左右孩子为根结点...
        return getNodeNumbers(2 * m, n) + getNodeNumbers(2 * m + 1, n) + 1;
    }
}
int main(){
    int m, n;
    while (cin>>m>>n) {
        if (m == 0 && n == 0) {
            break;
        }
        cout<<getNodeNumbers(m, n)<<endl;
    }
    return 0;
}

九、 搜索

9.1 广度优先搜索BFS

9.1.1 Catch that cow
#include<iostream>
#include<queue>
using namespace std;
const int MAXN = 1e5 + 10;
bool visited[MAXN]; //记录是否已经访问过某位置
struct Status{
    //记录当前状态(所处位置,已耗费时间)
    int position;
    int time;
    Status(int p, int t) : position(p), time(t){}
};
int BFS(int n, int k) {
    // n为农夫当前位置 ; k为牛的位置
    queue<Status> myQ;
    // 定义当前位置以及耗费时间
    visited[n] = true;
    // 起始位置入队
    myQ.push(Status(n, 0));
    while (!myQ.empty()) {
        Status current = myQ.front();
        if (current.position == k) {
            // 农夫已经遇到牛,结束BFS
            return current.time;
        } else {
            // 当前队首不是目标状态,出队
            myQ.pop();
            for (int i = 0; i < 3; i++) {
                // 每个状态后有三种状态选择
                Status next = current;
                if (i == 0) {
                    next.position += 1;
                } else if (i == 1) {
                    next.position -= 1;
                } else {
                    next.position *= 2;
                }
                if (next.position < 0 || next.position > 1e5 || visited[next.position]){
                    continue;
                }
                next.time += 1;
                myQ.push(next);
                visited[next.position] = true;
            }
        }
    }
}
int main(){
    int n, k;
    cin>>n>>k;
    cout<<BFS(n, k)<<endl;
    return 0;
}
9.1.2 Find the multiple
#include<iostream>
#include<queue>
using namespace std;
long long BFS(int n) {
    //找到一个数m,使得m = n*k,且m仅由0和1组成
    /*
        考虑以下方法:
        初始状态仅有一个数字1,其转移状态为10或11
        一般的,对于一个数字number,其转移状态为number*10或number*10+1
        使用广度优先搜索,逐个判断队头数字number是否满足number%n=0,若满足,则返回
    */
    queue<long long> number01;
    number01.push(1);
    while (!number01.empty()) {
        long long current = number01.front();
        number01.pop();
        if (current % n == 0) {
            return current;
        } else {
            number01.push(current * 10);
            number01.push(current * 10 + 1);
        }
    }
}
int main(){
    int n;
    while (cin>>n) {
        if (n == 0) {
            break;
        }
        cout<<BFS(n)<<endl;
    }
    return 0;
}

9.2 深度优先搜索DFS

9.2.1 A knight's journey
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 30;
bool visited[MAXN][MAXN];
int direction[8][2] = { {-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2} };
bool DFS(int x, int y, int step, string answer, int p, int q) {
    if (step == p * q) {
        cout<<answer<<endl<<endl;
        return true;
    } else {
        for (int i = 0; i < 8; i++) {
            int nx = x + direction[i][0];
            int ny = y + direction[i][1];
            //判断nx和ny是否合法
            if (nx < 0 || nx >=p || ny < 0 || ny >= q || visited[nx][ny]) {
                continue;
            }
            visited[nx][ny] = true;
            answer += ny + 'A';
            answer += nx + '1';
            if (DFS(nx, ny, step + 1, answer, p, q)) {
                return true;
            }
            visited[nx][ny] = false;
        }
    }
    return false;
}
int main(){
    int n;
    cin>>n;
    int caseNumber = 0;
    while (n--) {
        int p, q;
        cin>>p>>q;
        memset(visited, false, sizeof(visited));
        visited[0][0] = true;
        cout<<"Scenario #"<<++caseNumber<<":"<<endl;
        if (DFS(0, 0, 1, "A1", p, q)) {
            continue;
        } else {
            cout<<"impossible"<<endl<<endl;
        }
    }
    return 0;
}
9.2.2 Square
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 25;
bool visited[MAXN];
int sticks[MAXN];
bool Compare(int x, int y) {
    return x > y;
}
bool DFS(int m, int sum, int number, int side) {
    if (number == 3) {
        return true;
    } else {
        for (int i = 0; i < m; i++) {
            if (sum + sticks[i] > side || visited[i]) {
                continue;
            } 
            visited[i] = true;
            if (sum + sticks[i] == side) {
                if (DFS(m, 0, number+1, side)) {
                    return true;
                }
            } else {
                if (DFS(m, sum + sticks[i], number, side)) {
                    return true;
                }
            }
            visited[i] = false;
        }
    }
    return false;
}
int main(){
    int n;
    cin>>n;
    while (n--) {
        int m;
        cin>>m;
        int length = 0;
        for (int i = 0; i < m; i++) {
            cin>>sticks[i];
            length += sticks[i];
        }
        int side = length / 4;
        if (length % 4 != 0) {
            //不能构成正方形的四条边
            cout<<"no"<<endl;
            continue;
        }
        sort(sticks, sticks + m, Compare);
        if (sticks[0] > side) {
            cout<<"no"<<endl;
            continue;
        }
        if (DFS(m, 0, 0, side)) {
            cout<<"yes"<<endl;
        } else {
            cout<<"no"<<endl;
        }
    }
    return 0;
}

减枝处理

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 25;
bool visited[MAXN];
int sticks[MAXN];
bool Compare(int x, int y) {
    return x > y;
}
bool DFS(int m, int sum, int number, int p, int side) {
    if (number == 3) {
        return true;
    } else {
        int failSample = 0;
        for (int i = p; i < m; i++) {
            if (sum + sticks[i] > side || visited[i] || sticks[i] == failSample) {
                continue;
            }
            visited[i] = true;
            if (sum + sticks[i] == side) {
                if (DFS(m, 0, number+1, 0, side)) {
                    return true;
                } else {
                    failSample = sticks[i];
                }
            } else {
                if (DFS(m, sum + sticks[i], number, i + 1, side)) {
                    return true;
                } else {
                    failSample = sticks[i];
                }
            }
            visited[i] = false;
        }
    }
    return false;
}
int main(){
    int n;
    cin>>n;
    while (n--) {
        int m;
        cin>>m;
        int length = 0;
        for (int i = 0; i < m; i++) {
            cin>>sticks[i];
            length += sticks[i];
        }
        int side = length / 4;
        if (length % 4 != 0) {
            //不能构成正方形的四条边
            cout<<"no"<<endl;
            continue;
        }
        sort(sticks, sticks + m, Compare);
        if (sticks[0] > side) {
            cout<<"no"<<endl;
            continue;
        }
        memset(visited, false, sizeof(visited));
        if (DFS(m, 0, 0, 0, side)) {
            cout<<"yes"<<endl;
        } else {
            cout<<"no"<<endl;
        }
    }
    return 0;
}

十、 非线性数据结构

10.1 二叉树

10.1.1 二叉树遍历
#include<iostream>
#include<string>
using namespace std;
struct treeNode{
    char data;
    treeNode* leftChild;
    treeNode* rightChild;
    treeNode(char c) : data(c), leftChild(nullptr), rightChild(nullptr) {}
};
treeNode* buildTree(string preOrder, string inOrder) {
    if (preOrder.size() == 0) {
        return nullptr;
    }
    char c = preOrder[0];
    int position = inOrder.find(c);
    treeNode* root = new treeNode(c);
    root->leftChild = buildTree(preOrder.substr(1, position), inOrder.substr(0, position));
    root->rightChild = buildTree(preOrder.substr(position+1), inOrder.substr(position+1));
    return root;
}
void postOrder(treeNode* root){
    if (root == nullptr) {
        return;
    }
    postOrder(root->leftChild);
    postOrder(root->rightChild);
    cout<<root->data;
}
int main(){
    string str1, str2;
    while(cin>>str1>>str2) {
        treeNode* root = buildTree(str1, str2);
        postOrder(root);
        cout<<endl;
    }
    return 0;
}
10.1.2 二叉排序树
#include<iostream>
using namespace std;
struct treeNode{
    int data;
    treeNode* leftChild;
    treeNode* rightChild;
    treeNode(int n) : data(n), leftChild(nullptr), rightChild(nullptr) {}
};
treeNode* insertNode(treeNode* root, int data) {
    if (root == nullptr) {
        root = new treeNode(data);
    } else if (data > root->data) {
        root->rightChild = insertNode(root->rightChild, data);
    } else if (data < root->data) {
        root->leftChild = insertNode(root->leftChild, data);
    }
    return root;
}
void preOrder(treeNode* root) {
    if (root == nullptr) {
        return;
    }
    cout<<root->data<<" ";
    preOrder(root->leftChild);
    preOrder(root->rightChild);
}
void inOrder(treeNode* root) {
    if (root == nullptr) {
        return;
    }
    inOrder(root->leftChild);
    cout<<root->data<<" ";
    inOrder(root->rightChild);
}
void postOrder(treeNode* root) {
    if (root == nullptr) {
        return;
    }
    postOrder(root->leftChild);
    postOrder(root->rightChild);
    cout<<root->data<<" ";
}
int main(){
    int n;
    while (cin>>n){
        treeNode* root = nullptr;
        while (n--) {
            int data;
            cin>>data;
            root = insertNode(root, data);
        }
        preOrder(root);
        cout<<endl;
        inOrder(root);
        cout<<endl;
        postOrder(root);
        cout<<endl;
    }
    return 0;
}

10.2 优先队列

10.2.1 复数集合
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
struct Complex{
    int real;
    int imag;
    Complex(int a, int b) : real(a), imag(b) {}
    bool operator< (Complex c) const {
        if (c.imag * c.imag + c.real * c.real == imag * imag + real * real) {
            //模长相等,虚部较小者优先级高
            return c.imag < imag;
        } else {
            return c.imag * c.imag + c.real * c.real > imag * imag + real * real;
        }
    }
};
int main(){
    int n;
    while (cin>>n) {
        priority_queue<Complex> myQueue;
        while (n--) {
            string str;
            cin>>str;
            if (str == "Pop") {
                if (myQueue.empty()) {
                    cout<<"empty"<<endl;
                } else {
                    //弹出优先级最高的元素,并输出SIZE
                    Complex top = myQueue.top();
                    myQueue.pop();
                    cout<<top.real<<"+i"<<top.imag<<endl;
                    cout<<"SIZE = "<<myQueue.size()<<endl;
                }
            } else {
                //插入元素
                int a, b;
                scanf("%d+i%d", &a, &b);
                Complex c = Complex(a, b);
                myQueue.push(c);
                cout<<"SIZE = "<<myQueue.size()<<endl;
            }
        }
    }
    return 0;
}
10.2.2 哈夫曼树
#include<iostream>
#include<queue>
using namespace std;
int main(){
    int n;
    while (cin>>n) {
        priority_queue<int, vector<int>, greater<int> > Huffman;
        int answer = 0;
        while (n--) {
            int weight;
            cin>>weight;
            Huffman.push(weight);
        }
        while (Huffman.size() > 1) {
            int a = Huffman.top();
            Huffman.pop();
            int b = Huffman.top();
            Huffman.pop();
            int c = a + b;
            Huffman.push(c);
            answer += c;
        }
        cout<<answer<<endl;
    }
    return 0;
}

10.3 散列表

10.3.1 查找学生信息
#include<iostream>
#include<unordered_map>
#include<string>
using namespace std;
int main(){
    int n;
    cin>>n;
    unordered_map<string, string> students;
    getchar();
    while (n--) {
        string info;
        getline(cin, info);
        int position = info.find(" ");
        string key = info.substr(0, position);
        students[key] = info;
    }
    int m;
    cin>>m;
    while (m--) {
        string key;
        cin>>key;
        string answer;
        unordered_map<string, string>::iterator it = students.find(key);
        if (it != students.end()) {
            cout<<it->second<<endl;
        } else {
            cout<<"No Answer!"<<endl;
        }
    }
    return 0;
}

十一、 图论

11.1 并查集

11.1.1 连通图
#include<iostream>
using namespace std;
const int MAXN = 1000 + 10;
int father[MAXN];
int height[MAXN];
void Initial(int n){
    for (int i = 1; i <= n; i++) {
        //对每个结点初始化为一个集合
        father[i] = i;
        height[i] = 0;
    }
}
int Find(int x) {
    if (father[x] != x) {
        //压缩路径
        father[x] = Find(father[x]);
    }
    return father[x];
}
void Union(int x, int y){
    int f1 = Find(x); //得到元素x所在的集合
    int f2 = Find(y); //得到元素y所在的集合
    if (f1 != f2) {
        //进行合并操作,矮树加到高树上
        if (height[x] > height[y]) {
            father[y] = x;
        } else if (height[x] < height[y]) {
            father[x] = y;
        } else {
            //两个集合高度相同
            father[x] = y;
            height[y]++;
        }

    }
}
int main(){
    int n, m; //n为顶点个数,m为边数
    while (cin>>n>>m) {
        if (n == 0 && m == 0) {
            break;
        }
        Initial(n);
        while (m--) {
            int x, y;
            cin>>x>>y;
            Union(x, y);
        }
        int number = 0;
        for (int i = 1; i <= n; i++) {
            if (father[i] == i) {
                number++;
            }
        }
        if (number == 1 ) {
            cout<<"YES"<<endl;
        } else {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

11.2 最小生成树

11.2.1 还是畅通工程
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100 + 10;
int father[MAXN];
int height[MAXN];
struct Edge{
    int from;
    int to;
    int weight;
    bool operator< (Edge e) const {
        return weight < e.weight;
    }
};
Edge edges[MAXN*(MAXN-1)/2];
void Initial(int n){
    for (int i = 0; i <= n; i++) {
        father[i] = i;
        height[i] = 0;
    }
}
int Find(int x) {
    if (x != father[x]) {
        father[x] = Find(father[x]);
    }
    return father[x];
}
void Union(int x, int y) {
    int f1 = Find(x);
    int f2 = Find(y);
    if (f1 != f2) {
        if (height[f1] > height[f2]) {
            father[f2] = f1;
        } else if (height[f1] < height[f2]) {
            father[f1] = f2;
        } else {
            father[f1] = f2;
            height[f2]++;
        }
    }
}
int Kruskal(int n, int m) {
    Initial(n);
    int sum = 0;
    int selectedEdge = 0;
    sort(edges, edges + m);
    for (int i = 0; i < m; i++) {
        if (Find(edges[i].from) != Find(edges[i].to)) {
            Union(edges[i].from, edges[i].to);
            sum += edges[i].weight;
            selectedEdge++;
            //cout<<edges[i].from<<edges[i].to<<endl;
            if (selectedEdge == n-1) {
                break;
            }
        }
    }
    return sum;
}
int main(){
    int n;
    while (cin>>n) {
        if (n == 0) {
            break;
        }
        int m = n*(n-1)/2;
        for (int i = 0; i < m; i++) {
            cin>>edges[i].from>>edges[i].to>>edges[i].weight;
        }
        cout<<Kruskal(n, m)<<endl;
    }
    return 0;
}

☆注意Union函数中需要新定义f1和f2存放父结点

void Union(int x, int y) {
    int f1 = Find(x);
    int f2 = Find(y);
    if (f1 != f2) {
        if (height[f1] > height[f2]) {
            father[f2] = f1;
        } else if (height[f1] < height[f2]) {
            father[f1] = f2;
        } else {
            father[f1] = f2;
            height[f2]++;
        }
    }
}

11.3 最短路径

11.3.1 畅通工程续
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN = 200 + 10;
const int INF = INT_MAX;
struct Edge{
    int to;
    int length;
    Edge(int t, int l) : to(t), length(l) {}
};
struct Point{
    int number; //点的编号
    int distance; //起始点到该点的距离
    Point(int n, int d) : number(n), distance(d) {}
    bool operator< (Point p) const {
        return distance < p.distance;
    }
};
int dis[MAXN]; // 起始点到其他所有结点的距离
vector<Edge> graph[MAXN]; //邻接表
int Dijkstra(int start, int n) {
    // 进行初始化操作
    fill(dis, dis + n, INF);
    dis[start] = 0;
    priority_queue<Point> unSelectedPoint;
    unSelectedPoint.push(Point(start, dis[start]));
    while (!unSelectedPoint.empty()) {
        int u = unSelectedPoint.top().number;
        unSelectedPoint.pop();
        for (int i = 0; i < graph[u].size(); i++) {
            int v = graph[u][i].to;
            int d = graph[u][i].length;
            if (dis[u] + d < dis[v]) {
                dis[v] = dis[u] + d;
                unSelectedPoint.push(Point(v, dis[v]));
            }
        }
    }
}
int main(){
    int n, m; //n为顶点个数,m为路径信息
    while (cin>>n>>m) {
        memset(graph, 0, sizeof(graph));
        while (m--) {
            int from, to, length;
            cin>>from>>to>>length;
            graph[from].push_back(Edge(to, length));
            graph[to].push_back(Edge(from, length));
        }
        int start;
        int terminal;
        cin>>start>>terminal;
        Dijkstra(start, n);
        if (dis[terminal] == INF) {
            dis[terminal] = -1;
        }
        cout<<dis[terminal]<<endl;
    }
    return 0;
}

11.4 拓扑排序

11.4.1 确定比赛名次
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 500 + 10;
vector<int> graph[MAXN]; //邻接表
int inDegree[MAXN]; //记录每个点的入度
vector<int> topologicialSort(int n) {
    vector<int> topoSequence;
    priority_queue<int, vector<int>, greater<int> > myQueue;
    //先将入度为0的点存放到优先队列
    for (int i = 1; i <= n; i++) {
        if (inDegree[i] == 0) {
            myQueue.push(i);
        }
    }
    while (!myQueue.empty()) {
        int u = myQueue.top();
        myQueue.pop();
        topoSequence.push_back(u);
        // 删掉该顶点及其边,修改相连顶点的入度
        for (int i = 0; i < graph[u].size(); i++) {
            int v = graph[u][i];
            inDegree[v]--;
            if (inDegree[v] == 0) {
                myQueue.push(v);
            }
        }
    }
    return topoSequence;
}
int main(){
    int n, m;
    while (cin>>n>>m) {
        memset(graph, 0, sizeof(graph));
        memset(inDegree, 0, sizeof(inDegree));
        while (m--) {
            int from, to;
            cin>>from>>to;
            graph[from].push_back(to);
            inDegree[to]++;
        }
        vector<int> answer = topologicialSort(n);
        for (int i = 0; i < answer.size(); i++) {
            if (i == 0) {
                cout<<answer[i];
            } else {
                cout<<" "<<answer[i];
            }
        }
        cout<<endl;
    }
    return 0;
} 

11.5 关键路径

11.5.1 Instrction Arrangement

给你nm代表编号0 ~ n-1个任务(顶点),和m条关系(边),每条关系由X、Y、Z,代表想要完成Y必须先完成X并花费Z个时间、CPU可以同时完成多个任务处理,一次花费一个单位时间。问完成0 ~ n-1个任务需要多少时间。

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int MAXN = 1000 + 10;
struct Edge{
    int to;
    int length;
    Edge(int t, int l) : to(t), length(l) {}
};
vector<Edge> graph[MAXN];
int ve[MAXN];
int vl[MAXN];
int inDegree[MAXN];
void criticalPath(int n) {
    queue<int> myQueue;
    for (int i = 0; i < n; i++) {
        if (inDegree[i] == 0) {
            ve[i] = 1;
            myQueue.push(i);
        }
    }
    while (!myQueue.empty()) {
        int u = myQueue.front();
        myQueue.pop();
        for (int i = 0; i < graph[u].size(); i++) {
            int v = graph[u][i].to;
            int l = graph[u][i].length;
            ve[v] = max(ve[v], ve[u] + l);
            inDegree[v]--;
            if (inDegree[v] == 0) {
                myQueue.push(v);
            }
        }
    }
}
int main(){
    int n, m;
    while (cin>>n>>m) {
        memset(graph, 0, sizeof(graph));
        memset(ve, 0, sizeof(ve));
        memset(inDegree, 0, sizeof(inDegree));
        while (m--) {
            int from, to, length;
            cin>>from>>to>>length;
            graph[from].push_back(Edge(to, length));
            inDegree[to]++;
        }
        criticalPath(n);
        int answer = 0;
        for (int i = 0; i < n; i++) {
            answer = max(answer, ve[i]);
        }
        cout<<answer<<endl;
    }
    return 0;
}

十二、 动态规划

12.1 递推求解

12.1.1斐波那契数列(递推)
#include<iostream>
using namespace std;
const int MAXN = 100 + 10;
int f[MAXN];
int Fibonacci(int n) {
    for (int i = 0; i <= n; i++) {
        if (i == 0 || i == 1) {
            f[i] = i;
        } else {
            f[i] = f[i-1] + f[i-2];
        }
    }
    return f[n];
}
int main(){
    int n;
    cin>>n;
    cout<<Fibonacci(n)<<endl;
    return 0;
}

12.2 最大连续子序列和

12.2.1 最大序列和
#include<iostream>
using namespace std;
const int MAXN = 1e6 + 10;
const int INF = INT_MAX;
int f[MAXN];
int arr[MAXN];
void greatestSum(int n){
    for (int i = 0; i < n; i++) {
        //求出每个位置的最大序列和
        /*
            给定数列 -1 3 4 -8 6
            对于数3,索引为1,其对应的最大序列和为max(3, f(1) + 3)
        */
        if (i == 0) {
            f[i] = arr[i];
        } else {
            f[i] = max(arr[i], arr[i] + f[i-1]);
        }
    }
}
int main(){
    int n;
    while (cin>>n) {
        for (int i = 0; i < n; i++) {
            cin>>arr[i];
        }
        greatestSum(n);
        int answer = -INF;
        for (int i = 0; i < n; i++) {
            answer = max(answer, f[i]);
        }
        cout<<answer<<endl;
    }
    return 0;
}

12.3 最长递增子序列

12.3.1 Longest Ordered Subsequence
#include<iostream>
using namespace std;
const int MAXN = 1000 + 10;
int arr[MAXN];
int dp[MAXN];
void longestSequence(int n) {
    for (int i = 0; i < n; i++) {
        if (i == 0) {
            //第一个数字的最长递增子序列长为1
            dp[i] = 1;
        } else {
            dp[i] = 1; //初始化为1,如果可以形成递增子序列,再修改
            for (int j = 0; j < i; j++) {
                if (arr[j] < arr[i]) {
                    dp[i] = max(dp[i], dp[j]+1);
                }
            }
        }
    }
}
int main(){
    int n;
    cin>>n;
    for (int i = 0; i < n; i++) {
        cin>>arr[i];
    }
    longestSequence(n);
    int answer = 0;
    for (int i = 0; i < n; i++) {
        answer = max(answer, dp[i]);
    }
    cout<<answer<<endl;
    return 0;
}

12.4 最长公共子序列

12.4.1 Common subsequence
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = 1000 + 10;
char str1[MAXN];
char str2[MAXN];
int dp[MAXN][MAXN];
void commonSubsequence(int n, int m) {
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            if (i == 0 || j == 0) {
                dp[i][j] = 0;
            } else {
                if (str1[i] == str2[j]) {
                    dp[i][j] = dp[i-1][j-1] + 1;
                } else {
                    dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
    }
}
int main(){
    while (cin>>str1+1>>str2+1) {
        int n = strlen(str1 + 1);
        int m = strlen(str2 + 1);
        commonSubsequence(n, m);
        cout<<dp[n][m]<<endl;
        /*
        commonSubsequence(strlen(str1 + 1), strlen(str2 + 1));
        int answer = 0;
        for (int i = 0; i <= strlen(str1 + 1); i++) {
            for (int j = 0; j <= strlen(str2 + 1); j++) {
                answer = max(answer, dp[i][j]);
                //cout<<dp[i][j]<<" ";
            }
            //cout<<endl;
        }
        cout<<answer<<endl;
        */
    }
    return 0;
}

12.5 背包问题

12.5.1 点菜问题(0-1背包)
#include<iostream>
using namespace std;
const int MAXN = 1000 + 10;
int weight[MAXN];
int value[MAXN];
int dp[MAXN][MAXN];
int main(){
    int c, n;
    while (cin>>c>>n) {
        for (int i = 1; i <= n; i++) {
            cin>>weight[i]>>value[i];
        }
        //dp数组初始化
        for (int i = 0; i <= c; i++) {
            dp[i][0] = 0;
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = 0;
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= c; j++) {
                if (j < weight[i]) {
                    //dp[i][j]代表前i件物品装入容量为j的背包里能获得的最大价值
                    dp[i][j] = dp[i-1][j];
                } else {
                    dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]] + value[i]);
                }
            }
        }
        cout<<dp[n][c]<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 王道考研机试指南pdf是考研机试备考中的一本非常常用的参考书。它从计算机基本知识、算法和数据结构、操作系统、计算机网络、数据库系统等方面进行了全面的讲解,并附上了大量的例题和详细的解答。这本书的优点是内容翔实、系统全面,不仅覆盖了考研机试的所有科目范围,而且通过大量的例题和解答,让读者可以更好地理解和掌握机试中的知识点。在复习的过程中,读者也可以按照书中的章节,系统性地学习和巩固知识,从而提高复习效率。 此外,这本书还以考研机试的真实题目为蓝本,设计了练习题和模拟试题,让读者可以更好地了解考研机试的出题方式和难度。同时,本书的答案解析详细、清晰,读者可以针对自己的弱项进行有针对性的巩固。这本书不仅适合计算机专业的同学,也适合其他专业的学生进行参考。 总之,王道考研机试指南pdf是一本非常实用的备考参考书,通过学习这本书可以有效提高备考的效果,让考生在机试考场上更有把握。 ### 回答2: 王道考研机试指南pdf是一本内容丰富的考研机试指南电子书,对于准备参加考研机试的同学来说非常有价值。 本书从考试基础知识、数学、英语、计算机基础知识和程序设计五个部分展开,总共有44个章节。每个章节都有重点内容讲解和例题分析。其中重点讲解部分既深入浅出又充满实例,让学生能够轻松理解和掌握知识点;而例题分析部分则充满了技巧和考试注意事项,非常有助于提高考试得分。 此外,本书还包含了大量的机试真题,并针对真题进行细致的解析和分析,掌握这些真题有助于提升机试应试能力和水平。 总之,王道考研机试指南pdf是一本非常优秀的考研机试指南书籍,对于广大考生提高机试得分具有非常重要的参考意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值