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

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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容