算法笔记 第六章第七章第八章

8 篇文章 0 订阅
8 篇文章 0 订阅

第六章 标准模板库

A1039. Course List for Student

A1047. Student List for Course

 

使用map会超时

#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
using namespace std;
char name[40010][5];
vector<int> course[2510];
bool cmp1(int a, int b) {
    return strcmp(name[a], name[b]) < 0;
}
int main() {
    int n, k;
    scanf("%d %d", &n, &k);
    for(int i = 0; i < n; i++) {
        int cnt, temp;
        scanf("%s %d", name[i], &cnt);
        for(int j = 0; j < cnt; j++) {
            scanf("%d", &temp);
            course[temp].push_back(i);
        }
    }
    for(int i = 1; i <= k; i++) {
        printf("%d %d\n", i, course[i].size());
        sort(course[i].begin(), course[i].end(), cmp1);
        for(int j = 0; j < course[i].size(); j++)
            printf("%s\n", name[course[i][j]]);
    }
    return 0;
}

A1063. Set Similarity

A1060. Are They Equal

 

 

 

思路:把0和.全部清除掉,清除的过程中留下指数部分,剩下的字符串统计整数部分

 A.1100 Mars Numbers(?)

#include <iostream>
#include <string>
using namespace std;
string a[13] = {"tret", "jan", "feb", "mar", "apr", "may", "jun", "jly", "aug", "sep", "oct", "nov", "dec"};
string b[13] = {"####", "tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mer", "jou"};
string s;
int len;
void func1(int t) {
    if (t / 13) cout << b[t / 13];
    if ((t / 13) && (t % 13)) cout << " ";
    if (t % 13 || t == 0) cout << a[t % 13];
}
void func2() {
    int t1 = 0, t2 = 0;
    string s1 = s.substr(0, 3), s2;
    if (len > 4) s2 = s.substr(4, 3);
    for (int j = 1; j <= 12; j++) {
        if (s1 == a[j] || s2 == a[j]) t2 = j;
        if (s1 == b[j]) t1 = j;
    }
    cout << t1 * 13 + t2;
}
int main() {
    int n;
    cin >> n;
    getchar();
    for (int i = 0; i < n; i++) {
        getline(cin, s);
        len = s.length();
        if (s[0] >= '0' && s[0] <= '9')
            func1(stoi(s));
        else
            func2();
        cout << endl;
    }
    return 0;
}

A.1054 The Dominant Color

A.1071 Speech Patterns

A. 1022 Digital Libaray

第七章 数据结构专题

栈 A1051.Pop Sequence

模拟元素入栈,每次将1~n压入栈中,每次压完比较栈顶元素和当前出栈元素是否相等,相等则弹出栈顶元素,并将出栈元素的位置右移。依次比较。当栈中的容量超过M时,或者最后栈不为空,说明当前出栈顺序不可能。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int arr[maxn];
stack<int> st;
int main() {
    int m, n, T;
    cin>> m >> n >> T;
    while(T--) {
        while(!st.empty()){
            st.pop();
        }
        for (int i = 1; i <= n; i++) {
            cin>>arr[i];
        }
        int current = 1;
        bool flag = true;
        for (int i = 1; i<= n; i++) {
            st.push(i);
            if(st.size() > m) {
                flag = false;
                break;
            }
            while(!st.empty() && st.top() == arr[current]) {
                st.pop();
                current++;
            }
        }
        if(st.empty()  && flag == true) {
            printf("YES\n");
        } else {
            printf("NO\n");
        }
    }
    return 0;
}

队列 A1056. Mice and Rice

思路:结构体mice包括排名和重量。然后设置一个队列,队列里面放入排序编号,然后每次取NG只,找出最大的再放到队列里面。依次进行直到队列只剩下一个元素。注意排名等于每次的group+1(group为组数)。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;
struct mouse {
    int weight;
    int R;
} mice[maxn];

int main() {
    int np, ng, order;
    cin>>np>>ng;
    for (int i = 0; i < np; i++) {
        cin>>mice[i].weight;
    }
    queue<int> q;
    for (int i = 0; i < np; i++) {
        cin>>order;
        q.push(order);
    }
    int temp = np, group;
    while (q.size() != 1) {
        if (temp % ng == 0) group = temp / ng;
        else group = temp / ng + 1;
        for (int i = 0; i < group; i++) {
            int k = q.front();
            for (int j = 0; j < ng; j++) {
                if(i * ng + j >= temp) {
                    break;
                }
                int front = q.front();
                if(mice[front].weight > mice[k].weight) {
                    k = front;
                }
                mice[front].R = group + 1;
                q.pop();
            }
            q.push(k);
        }
        temp = group;//下一輪老鼠总数为group
    }
    mice[q.front()].R = 1;
    for (int i = 0; i < np; i++) {
        cout<<mice[i].R;
        if(i < np - 1) cout<<" ";
    }
    return 0;
}

A1074. 反转链表

注意细节处理就行。就是每k个进行翻转。这里用的是静态链表。因为有一些无效的节点,所以结构体需要一个字段表示是否是有效结点。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct Node {
    int address, data, next;
    int order;//节点在链表上的序号,无效节点标记为maxn
} node[maxn];
bool cmp(Node a, Node b) {
    return a.order < b.order;
}

int main() {
    for (int i = 0; i < maxn; i++) {
        node[i].order = maxn;
    }
    int begin, n, K, address;
    cin>>begin>>n>>K;
    for (int i = 0; i < n; i++) {
        cin>>address;
        cin>>node[address].data>>node[address].next;
        node[address].address = address;
    }
    int p = begin, count = 0;
    while(p != -1) {
        node[p].order = count++;
        p = node[p].next;
    }
    sort(node, node + maxn, cmp);
    n = count;
    for (int i = 0; i < n / K; i++) {
        for(int j = (i + 1) * K - 1; j > i * K; j--) {//第i块倒着输出
            printf("%05d %d %05d\n",node[j].address,node[j].data,node[j-1].address);
        }
        printf("%05d %d ",node[i * K].address, node[i * K].data);
        if(i < n / K - 1) {//不是最后一块,就指向下一块的最后一个节点
            printf("%05d\n",node[(i + 2) * K - 1].address);
        } else { //是最后一块时
            if(n % K == 0) { //恰好是最后一个节点
                printf("-1\n");
            } else {
                printf("%05d\n", node[(i+1)*K].address);
                for (int i = (n / K) * K; i < n; i++) {
                    printf("%05d %d ",node[i].address, node[i].data);
                    if (i < n - 1){
                        printf("%05d\n", node[i+1].address);
                    } else {
                        printf("-1\n");
                    }
                }
            }
        }
    }
    return 0;
}

A1032. Sharing 

求出两个链表的第一个共用节点。只需要把第一个链表每个节点存到数组里面,每个结构体增加一个flag字段表明这个节点有效(出现在第一个链表里面),然后遍历第二个链表求出第一个出现在第一个链表的节点。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 100010;
struct NODE{
    char data;
    int next;
    bool flag;//节点是否在第一条链表出现
}node[maxn];
int main() {
    for (int i = 0; i < maxn; i ++ ){
        node[i].flag = false;
    }
    int s1, s2, n;
    if(scanf("%d%d%d", &s1, &s2, &n)){};
    int address,next;
    char data;
    for (int i = 0; i < n; i ++) {
           if(scanf("%d %c %d", &address, &data, &next)){};
        node[address].data = data;
        node[address].next = next;
    }
    int p;
    for (p = s1; p != -1; p = node[p].next) {
        node[p].flag = true;
    }
    for (p = s2; p != -1; p = node[p].next) {
        if(node[p].flag == true) break;
    }
    if(p != -1){
        printf("%05d\n",p);
    }else{
        cout<<"-1"<<endl;
    }
    return 0;
}

A1052. Linked List Sorting

链表排序:静态数组形式排序,只需要重写cmp方法,有效结点和无效节点比较时, 需要将有效的节点全部放在无效节点前面。有效结点和有效结点比较时,需要将值较小的放在前面。排好序顺序输出即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct Node{
    int address, data, next;
    bool flag;
}node[maxn];
bool cmp(Node a, Node b) {
    if (a.flag == false || b.flag == false) {
        return a.flag > b.flag ;
    } else{
        return a.data < b.data;
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    for (int i = 0; i < maxn; i ++) {
        node[i].flag = false;
    }
    int n, begin, address;
    cin >> n >> begin;
    for (int i = 0; i < n; i ++) {
        cin >>address;
        cin >> node[address].data >> node[address].next ;
        node[address].address = address;
    }
    int count = 0, p =begin;
    while(p != -1) {
        node[p].flag = true;
        count ++;
        p = node[p].next;
    }
    if(count == 0) {
        cout<<"0 -1";
    } else {
        sort(node,node+maxn, cmp);
        printf("%d %05d\n",count,node[0].address);
        for (int i = 0; i < count; i ++) {
            if (i != count -1) {
                printf("%05d %d %05d\n",node[i].address, node[i].data, node[i+1].address);
            } else {
                printf("%05d %d -1\n",node[i].address, node[i].data);
            }
        }
    }
    return 0;
}

A1097. Deduplication on a Linked List

要把绝对值相同的多余节点删了,留下第一个。那么可以定义一个数组,出现过的标记一下。然后统计留下来的节点个数和删除的节点个数。结构体一个字段order表示输出顺序。留下的节点order小,删除的节点order大。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1000010;
struct Node {
    int address, data, next;
    int order;
} node[maxn];
bool isExist[maxn] = {false};
bool cmp(Node a, Node b) {
    return a.order < b.order;
}

int main() {
    memset(isExist,false, sizeof(isExist)) ;
    for (int i = 0; i < maxn; i++) {
        node[i].order = 2 * maxn;
    }
    int n, begin, address;
    cin>>begin>>n;
    for (int i = 0; i < n; i++) {
        cin>>address;
        cin>>node[address].data>>node[address].next;
        node[address].address = address;
    }
    int countValid = 0, countRemoved = 0, p = begin;
    while (p != -1) {
        if(!isExist[abs(node[p].data)]) {
            isExist[abs(node[p].data)] = true;
            node[p].order = countValid ++;
        } else {
            node[p].order = maxn + countRemoved++;
        }
        p = node[p].next;
    }
    sort(node, node + maxn, cmp);
    int count = countValid + countRemoved;
    for (int i = 0; i < count; i++) {
        if (i != countValid - 1 && i != count -1) {
            printf("%05d %d %05d\n", node[i].address,node[i].data,node[i+1].address);
        } else {
            printf("%05d %d -1\n", node[i].address,node[i].data);
        }
    }
    return 0;
}

第八章 搜索专题

DFS A1103 Integer Factorization

首先:用一个数组将候选的数全部存起来。fac[i] = i^p。DFS用于从fac选择若干个数。

DFS参数有:①当前处理到的fac的第几个数,②已经选择了几个数nowK③当前选择的数的和④当前选择出的最小底数和

为了获取字典序最大的序列,让index从大到小进行遍历就行。

#include<bits/stdc++.h>
using namespace std;
int n, k, p, maxFacSum = -1;
vector<int> fac, ans, temp;
int power(int x) {
    int ans = 1;
    for(int i = 0; i < p; i++) {
        ans *= x;
    }
    return ans;
}
void init(){
    int i = 0;
    int temp = 0;
    while(temp <= n) {
        fac.push_back(temp);
        temp = power(++i);
    }
}
void DFS(int index, int nowK, int sum, int facSum){
    if(sum == n && nowK == k) {
        if(facSum > maxFacSum ) {
            ans = temp;
            maxFacSum = facSum;
        }
        return ;
    }
    if(sum > n || nowK > k) return;
    if(index - 1 >= 0) {//fac[0]不用选择
        temp.push_back(index);
        DFS(index,nowK+1,sum+fac[index],facSum+index);//选
        temp.pop_back();
        DFS(index - 1,nowK,sum,facSum);//不选
    }
}
int main(){
    cin>>n>>k>>p;
    init();
    DFS(fac.size()-1,0,0,0);
    if(maxFacSum == -1) printf("Impossible\n");
    else{
        printf("%d = %d^%d",n,ans[0],p);
        for(int i = 1;i < ans.size(); i++) {
            printf(" + %d^%d",ans[i],p);
        }
    }
}

BFS A1091. Acute Stroke

一个三维空间的块统计而已,换汤不换药。看懂题目才难。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int x, y, z;
} Node;
int n, m, slice1, T;
int pixel[1290][130][61];//三维矩阵
bool inq[1290][130][61] = {false};
int X[6] ={0,0,0,0,1,-1};
int Y[6] ={0,0,1,-1,0,0};
int Z[6] ={1,-1,0,0,0,0};
bool judge(int x, int y, int z) {
    if(x >= n || x < 0 || y >= m || y < 0 || z >= slice1 || z < 0) return false;
    if(pixel[x][y][z] == 0 || inq[x][y][z] == true) return false;
    return true;
}
int BFS(int x, int y, int z) {
    int tot = 0;
    queue<node> Q;
    Node.x = x, Node.y = y, Node.z = z;
    Q.push(Node);
    inq[x][y][z] = true;
    while(!Q.empty()) {
        node top = Q.front();
        Q.pop();
        tot ++;
        for(int i = 0; i < 6; i++) {
            int newX = top.x + X[i];
            int newY = top.y + Y[i];
            int newZ = top.z + Z[i];
            if(judge(newX, newY, newZ)) {
                Node.x = newX, Node.y = newY, Node.z = newZ;
                Q.push(Node);
                inq[newX][newY][newZ] = true;
            }
         } 
    }
    if(tot >= T) return tot;
    else return 0;
}

int main() {
    if(scanf("%d%d%d%d",&n,&m,&slice1,&T)){};
    for(int z = 0; z < slice1; z++) {
        for(int x = 0; x < n; x++) {
            for (int y = 0; y < m; y++) {
                if(scanf("%d",&pixel[x][y][z])){};
            }
        }
    }
    int ans = 0;
    for(int z = 0; z < slice1; z++) {
        for(int x = 0; x < n; x++) {
            for (int y = 0; y < m; y++) {
                if(pixel[x][y][z] == 1 && inq[x][y][z] == false){
                    ans += BFS(x,y,z);
                }
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

 第九章  数据结构专题(2)

二叉树 A1020. Tree Traversals

根据中序和后序构造前序,然后层序遍历

#include<bits/stdc++.h>
using namespace std;
struct node {
    int data;
    node* lchild;
    node* rchild;
};
const int maxn = 50;
int pre[maxn], in[maxn], post[maxn];
int n;
node* create(int postL,int postR, int inL, int inR) {
    if(postL > postR) return NULL;
    node* root = new node;
    root->data = post[postR];
    int k;
    for(k = inL; k <= inR; k++) {
        if(in[k] == post[postR]) {
            break;
        }
    }
    int numLeft = k - inL;
    root->lchild = create(postL, postL + numLeft - 1,inL, k - 1);
    root->rchild = create(postL + numLeft, postR - 1, k + 1, inR);
    return root;
}
int num = 0;
void BFS(node* root) {
    queue<node*> q;
    q.push(root);
    while(!q.empty()) {
        node* now = q.front();
        q.pop();
        cout<<now->data;
        num ++;
        if(num < n) cout<<" ";
        if(now->lchild != NULL) q.push(now->lchild);
        if(now->rchild != NULL) q.push(now->rchild);
    }
}
int main(){
    cin>>n;
    for (int i = 0; i < n; i ++) {
        cin>>post[i];
    }
    for (int i = 0; i < n; i ++) {
        cin>>in[i];
    }
    node* root = create(0, n - 1, 0, n - 1);
    BFS(root);
    return 0;
}

A1086. Tree Traversals Again

根据先序和中序求后序,换汤不换药

A1102. Invert a Binary Tree

反转:后序遍历递归写法:先反转叶子节点,再往上反转。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;
struct node {
    int lchild, rchild;
} Node[maxn];

bool notRoot[maxn] = {false};//记录师傅不是根节点,初始时刻均是根节点
int n, num = 0;//n为节点个数,num为已经输出的节点个数
void print(int id) {
    printf("%d",id);
    num ++;
    if(num < n) printf(" ");
    else printf("\n");
}

void inOrder(int root) {//中序遍历
    if(root == -1) return;
    inOrder(Node[root].lchild);
    print(root);
    inOrder(Node[root].rchild);
}
void BFS(int root) {
    queue<int> q;
    q.push(root);
    while(!q.empty()) {
        int now = q.front();
        q.pop();
        print(now);
        if(Node[now].lchild != -1) q.push(Node[now].lchild);
        if(Node[now].rchild != -1) q.push(Node[now].rchild);
    }
}
//后序遍历,用以反转二叉树
void postOrder(int root) {
    if (root == -1) return ;
    postOrder(Node[root].lchild);
    postOrder(Node[root].rchild);
    swap(Node[root].lchild,Node[root].rchild);
}
int strToNum(char c) {
    if(c == '-') return -1;
    else {
        notRoot[c - '0'] = true;
        return c - '0';
    }
}

int findRoot() {
    for (int i = 0; i < n; i++) {
        if(notRoot[i] == false){
            return i;
        }
    }
    return -1;
}
int main() {
    char lchild, rchild;
    cin>>n;
    for(int i = 0; i < n; i++) {
        cin>>lchild>>rchild;
        Node[i].lchild = strToNum(lchild);
        Node[i].rchild = strToNum(rchild);
    }
    int root = findRoot();
    postOrder(root);
    BFS(root);
    num = 0;
    inOrder(root);
    return 0;
}

树的遍历 A1079 Total Sales of Supply Chain

题意:给出一棵销售供应的树,树根唯一。树根处货物的价格为P,然后从树根节点每往子节点走一层,该层的货物价格会在父节点的价格上增加r%,给出每个叶节点的货物量,求他们的价格之和。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct node {
    double data;
    vector<int> child;//指针域
} Node[maxn];
int n;
double p, r, ans = 0;
void DFS(int index, int depth) {
    if(Node[index].child.size() == 0) {
        ans += Node[index].data * pow(1 + r, depth);
        return;
    }
    for (unsigned int i = 0; i < Node[index].child.size(); i++){
        DFS(Node[index].child[i], depth + 1);
    }
}
int main() {
    int k, child;
    if(scanf("%d%lf%lf",&n,&p,&r)){};
    r /= 100;
    for(int i = 0; i < n; i++) {
        if(scanf("%d",&k)){};
        if(k == 0) {
            if(scanf("%lf",&Node[i].data)){};
        } else {
            for (int j = 0; j < k; j++) {
                if(scanf("%d",&child)){};
                Node[i].child.push_back(child);
            }
        }
    }
    DFS(0,0);
    printf("%.1f\n",p*ans);
    return 0;
}

A1090 Highest Price in Supply Chain

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
vector<int> child[maxn];
int n;
double p, r, ans = 0;
int num = 0, maxDepth = 0;
void DFS(int index, int depth) {
    if(child[index].size() == 0) {
        if(depth > maxDepth) {
            maxDepth = depth;
            num = 1;
        } else if(depth == maxDepth) {
            num ++;
        }
        return;
    }
    for (unsigned int i = 0; i < child[index].size(); i++) {
        DFS(child[index][i], depth + 1);
    }
}

int main() {
    int father, root;
    if(scanf("%d%lf%lf", &n, &p, &r)){};
    r /= 100;
    for(int i = 0; i < n; i++) {
        if(scanf("%d",&father)){};
        if(father != -1) {
            child[father].push_back(i);
        } else {
            root = i;
        }
    }
    DFS(root,0);
    printf("%.2f %d\n", p * pow(1 + r,maxDepth), num);
    return 0;
}

A1094 The Largest Generation

题意:求节点个数最多的一层,并且输出节点个数和层号

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 110;
vector<int> Node[MAXN];
int hashTable[MAXN] ={0};
void DFS(int index, int level) {
    hashTable[level] ++;
    for (unsigned int j = 0; j < Node[index].size(); j++) {
        DFS(Node[index][j], level + 1);
    }
}
int main() {
    int n, m, parent, k, child;
    if(scanf("%d%d",&n,&m)){};
    for (int i = 0; i < m; i++) {
        if(scanf("%d%d",&parent,&k)){};
        for (int j = 0; j < k; j++) {
            if(scanf("%d",&child)){};
            Node[parent].push_back(child);
        }
    }
    DFS(1,1);
    int maxLevel = -1, maxValue = 0;
    for(int i = 1; i < MAXN; i++) {
        if(hashTable[i] > maxValue) {
           maxValue = hashTable[i];
            maxLevel = i;
        }

    }
    printf("%d %d\n",maxValue,maxLevel);
    return 0;
}

A1106 Lowest Price in Supply Chain (25 分)

A1104 Sum of Number Segments (20 分)

A1053 Path of Equal Weight (30 分)

二叉查找树 A1043 Is It a Binary Search Tree (25 分)

struct node {
    int data;
    node* left, *right;
};
void insert(node* &root, int data) {
    if(root == NULL) {
        root = new node;
        root->data = data;
        root->left = root->right = NULL;
        return;
    }
    if(data < root->data) {
        insert(root->left,data)
    }
    else {
        insert(root->right,data);
    }
}
void preOrder(node* root, vector<int>& vi) {
    if(root == NULL) {
        return;
    }
    vi.push_back(root->data);
    preOrder(root->left,vi);
    preOrder(root->right,vi);
}
void preOrderMirror(node* root, vector<int>& vi) {
    if(root == NULL) return;
    vi.push_back(root->data);
    preOrderMirror(root->right);
    preOrderMirror(root->left);
}
void postOrder(node* root, vector<int>& vi) {
    if(root == NULL) {
        return;
    }
    postOrder(root->left,vi);
    vi.push_back(root->data);
    postOrder(root->right,vi);
}
void postOrderMirror(node* root, vector<int>& vi) {
    if(root == NULL) return;
    postOrderMirror(root->right);
        vi.push_back(root->data);
    postOrderMirror(root->left);
}

 

A1064 Complete Binary Search Tree

A1099 Build A Binary Search Tree

平衡二叉树 A1066 Root of AVL Tree

并差集 A1107 Social Clusters

堆 A1098 Insertion or Heap Sort 

第十章 图算法专题

图的遍历 A1013 Battle Over Cities

A1021 Deepest Root

A1034 Head of a Gang

A1076 Forwards on Weibo

最短路径 A1003 Emergency 

A1018 Public Bike Management

A1030 Travel Plan

A1072 Gas Station

A1087 All Roads Lead to Rome 

动态规划 A1007 最大连续子序列和

最长不下降子序列 A1045. Favorite Color Stripe

最长公共子序列 A1045 Favorite  Color Stripe

最长回文字符串 A1040 Longest Symmetric String

背包问题A1068 Find More Coins

第12章 字符串专题

字符串hash A1040 Longest Symmetric String

分块 A1057 Stack

树状数组 A1057 Stack

快乐模拟 A1105 螺旋矩阵

A1017 Queueing at Bank

A1014 Waitting in Line

A1026 Table Tennis

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值