美文网首页
All for PAT秋考 | 可能是2016.3甲级

All for PAT秋考 | 可能是2016.3甲级

作者: zilla | 来源:发表于2019-08-10 21:00 被阅读0次
20 25 25 30

输入处理

  • sstream
#include <iostream>
#include <sstream>

stringstream ss;
string str;
// ss.clear();
cin >> str;
ss << str;
if (str[0]!='-') {
    int a;
    ss >> a;
    cout << a;
}
  • sprintf
#include <cstdio>

char curr_format[110], curr_num[110];; 
scanf("%s", curr_num);
sscanf(curr_num, "%lf", &curr_in);
sprintf(curr_format, "%.2lf", curr_in);

花里胡哨最短路的注意点

  • 图的存储尽量用邻接矩阵(回溯方便)

  • Dijkstra得最短路径长度,维护pre数组(set<int> pre[MAXN]map<int, set<int>> pre),DFS回溯得到具体路径(注意传参,注意递归边界,注意路径维护)。

1108 Finding Average (20 分)

#include <cstdio>

int main() {
    int nn, cnt = 0;
    double total = 0.0;
    scanf("%d", &nn);
    char curr_num[110];
    while (nn--) {
        double curr_in;
        char curr_format[110];
        scanf("%s", curr_num);
        sscanf(curr_num, "%lf", &curr_in);
        sprintf(curr_format, "%.2lf", curr_in);
        int in_format = 1;
        for (int i = 0; curr_num[i]; ++i) {
            if (curr_num[i] != curr_format[i]) {
                in_format = 0;
                break;
            }
        }
        if (in_format) {
            if (curr_in < -1000 || curr_in > 1000) {
                in_format = 0;
            }
        }
        if (in_format) {
            total += curr_in;
            cnt++;
        } else {
            printf("ERROR: %s is not a legal number\n", curr_num);
        }
    }
    if (cnt == 0) {
        printf("The average of 0 numbers is Undefined\n");
    } else if (cnt == 1) {
        printf("The average of 1 number is %.2lf\n", total / cnt);
    } else {
        printf("The average of %d numbers is %.2lf\n", cnt, total / cnt);
    }
    return 0;
}

1109 Group Photo (25 分)

#include <cstdio>
#include <string>
#include <algorithm>

using namespace std;
struct Person {
    string name;
    int HH;
} people[10001];

bool cmp(const Person &p1, const Person &p2) {
    if (p1.HH != p2.HH) return p1.HH > p2.HH;
    return p1.name < p2.name;
}

int main() {
    int form[10][10001];
    int nn, nrow;
    scanf("%d%d", &nn, &nrow);
    char name[10];
    for (int i = 0; i < nn; ++i) {
        scanf("%s%d", name, &people[i].HH);
        people[i].name = name;
    }
    sort(people, people + nn, cmp);
    int n_each = nn / nrow;
    int n_last = nn % n_each + n_each;
    int curr = 0;
    form[0][n_last / 2] = curr++;
    for (int i = 1; i <= n_last / 2; i++) {
        if (n_last / 2 - i >= 0)form[0][n_last / 2 - i] = curr++;
        if (n_last / 2 + i < n_last)form[0][n_last / 2 + i] = curr++;
    }
    for (int i = 0; i < n_last; ++i) {
        printf("%s", people[form[0][i]].name.data());
        printf(i == n_last - 1 ? "\n" : " ");
    }
    for (int i = 1; i < nrow; ++i) {
        form[i][n_each / 2] = curr++;
        for (int j = 1; j <= n_each / 2; ++j) {
            if (n_each / 2 - j >= 0) form[i][n_each / 2 - j] = curr++;
            if (n_each / 2 + j < n_each) form[i][n_each / 2 + j] = curr++;
        }
    }
    for (int k = 1; k < nrow; ++k) {
        for (int i = 0; i < n_each; ++i) {
            printf("%s", people[form[k][i]].name.data());
            printf(i == n_each - 1 ? "\n" : " ");
        }
    }
    return 0;
}

1110 Complete Binary Tree (25 分)

判断是否为完全二叉树(下标从0开始)

  • 在读入时判断:若左孩子不存在且右孩子存在,则不是CBT,结束。若是,下一步。
    (读入时还要确定根结点)
  • 递归建树时判断:若位置为pos的结点x左孩子存在,且左孩子结点位置2*pos + 1 >= 结点数,则不是CBT,结束。
  • 返回,是。

若建树后再判断是否为完全二叉树,也可考虑下面的方法。



选择在建树时判断的原因是,使用了数组来实现二叉树,直接建树若形成一棵链条状的数,需要的空间将达到指数级⚠️。

#include <iostream>
#include <string>
#include <sstream>

using namespace std;
int NN, btree[101], child[21][2];
bool isRoot[21];

bool createTree(int pos, int key) {
    btree[pos] = key;
    int lc = child[key][0], rc = child[key][1];
    if (lc != -1 && 2 * pos + 1 >= NN) return false;
    if (rc != -1) { // lc rc
        if (!createTree(2 * pos + 1, lc))
            return false;
        if (!createTree(2 * pos + 2, rc))
            return false;
    } else if (lc != -1) { // lc -
        if (!createTree(2 * pos + 1, lc))
            return false;
    }
    return true;
}

int main() {
    fill(isRoot, isRoot + 21, true);
    bool isBT = true;
    cin >> NN;
    stringstream ss;
    for (int i = 0; i < NN; ++i) {
        string sl, sr;
        int lc = -1, rc = -1;
        cin >> sl >> sr;
        if (sl[0] != '-') {
            ss.clear();
            ss << sl;
            ss >> lc;
            isRoot[lc] = false;
        }
        if (sr[0] != '-') {
            ss.clear();
            ss << sr;
            ss >> rc;
            isRoot[rc] = false;
        }
        child[i][0] = lc, child[i][1] = rc;
        if (lc == -1 && rc != -1) isBT = false;
    }
    int root = 0;
    for (; root < NN; ++root) {
        if (isRoot[root]) break;
    }
    if (!isBT) {
        printf("NO %d\n", root);
        return 0;
    }
    if (createTree(0, root)) {
        printf("YES %d\n", btree[NN - 1]);
    } else printf("NO %d\n", root);
    return 0;
}

1111 Online Map (30 分)

  • 分别按照路径长度,耗时进行一次Dijkstra,并分别建立前驱结点集合.
  • 按照Dijkstra的前驱结点集合,分别DFS回溯。注意在递归时维护路径,在递归边界时,更新最佳路径。注意DFS的传参。
  • ⚠️ 能用邻接矩阵,就别用邻接表(pre集合回溯时,邻接矩阵比邻接表方便不少)
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;
const int INF = 0x3fffffff;
int nn, mm, src, target;
struct Way {
    int len = INF, time = INF;
};
int mtime = INF, mdepth = INF;
vector<int> best_time_path, temp_time_path, shortest, temp_shortest;
Way graph[501][501];
int min_dist[501], min_time[501];
map<int, set<int> > dpre, tpre;

void Dijkstra_length(int root) {
    fill(min_dist, min_dist + 501, INF);
    bool visited[501] = {false};
    min_dist[root] = 0;
    for (int i = 0; i < nn; ++i) {
        int curr = -1, mmin = INF;
        for (int j = 0; j < nn; ++j) {
            if (!visited[j] && min_dist[j] < mmin) {
                mmin = min_dist[j];
                curr = j;
            }
        }
        if (curr != -1) {
            visited[curr] = true;
            for (int k = 0; k < nn; k++) {
                if (graph[curr][k].len != INF) {
                    int new_dist = min_dist[curr] + graph[curr][k].len;
                    if (new_dist < min_dist[k]) {
                        min_dist[k] = new_dist;
                        dpre[k].clear();
                        dpre[k].insert(curr);
                    } else if (new_dist == min_dist[k]) {
                        dpre[k].insert(curr);
                    }
                }
            }
        } else return;
    }
}

void Dijkstra_time(int root) {
    fill(min_time, min_time + 501, INF);
    bool visited[501] = {false};
    min_time[root] = 0;
    for (int i = 0; i < nn; ++i) {
        int curr = -1, mmin = INF;
        for (int j = 0; j < nn; ++j) {
            if (!visited[j] && min_time[j] < mmin) {
                mmin = min_time[j];
                curr = j;
            }
        }
        if (curr != -1) {
            visited[curr] = true;
            for (int k = 0; k < nn; k++) {
                if (graph[curr][k].len != INF) {
                    int newt = min_time[curr] + graph[curr][k].time;
                    if (newt < min_time[k]) {
                        min_time[k] = newt;
                        tpre[k].clear();
                        tpre[k].insert(curr);
                    } else if (newt == min_time[k]) {
                        tpre[k].insert(curr);
                    }
                }
            }
        } else return;
    }
}

void DFS(int root, int time_sum) { // according to dpre[root]
    if (root == src) {
        temp_shortest.emplace_back(root);
        if (time_sum < mtime) {
            shortest = temp_shortest;
            mtime = time_sum;
        }
        temp_shortest.pop_back();
        return;
    }
    temp_shortest.emplace_back(root);
    for (auto item:dpre[root]) {
        DFS(item, time_sum + graph[item][root].time);
    }
    temp_shortest.pop_back();
}

void DFS_depth(int root, int depth) { // according to tpre[]
    if (root == src) {
        temp_time_path.emplace_back(root);
        if (depth < mdepth) {
            best_time_path = temp_time_path;
            mdepth = depth;
        }
        temp_time_path.pop_back();
        return;
    }
    temp_time_path.emplace_back(root);
    for (auto item:tpre[root]) {
        DFS_depth(item, depth + 1);
    }
    temp_time_path.pop_back();
}

int main() {
    scanf("%d%d", &nn, &mm);
    int v1, v2, one_way, length, time;
    for (int i = 0; i < mm; ++i) {
        scanf("%d%d%d%d%d", &v1, &v2, &one_way, &length, &time);
        graph[v1][v2].len = length, graph[v1][v2].time = time;
        if (one_way == 0) graph[v2][v1].len = length, graph[v2][v1].time = time;;
    }
    scanf("%d%d", &src, &target);
    Dijkstra_length(src);
    Dijkstra_time(src);
    DFS(target, 0); // get one path with min_time
    DFS_depth(target, 1); // get one path with min_intersection
    if (shortest == best_time_path) {
        printf("Distance = %d; Time = %d: ", min_dist[target], mtime);
        for (int i = mdepth - 1; i >= 0; --i) {
            printf("%d", shortest[i]);
            printf(i == 0 ? "\n" : " -> ");
        }
    } else {
        printf("Distance = %d: ", min_dist[target]);
        for (int i = shortest.size() - 1; i >= 0; --i) {
            printf("%d", shortest[i]);
            printf(i == 0 ? "\n" : " -> ");
        }
        printf("Time = %d: ", min_time[target]);
        for (int i = mdepth - 1; i >= 0; --i) {
            printf("%d", best_time_path[i]);
            printf(i == 0 ? "\n" : " -> ");
        }
    }
    return 0;
}

相关文章

网友评论

      本文标题:All for PAT秋考 | 可能是2016.3甲级

      本文链接:https://www.haomeiwen.com/subject/etrdjctx.html