• PAT甲级 刷题DAY1 1001-1010 题解


    1001 A+B Format

    用时6分钟

    先计算a+b,再转换成字符串,再转换成字符数组,从后往前扫一遍,每3位加一个逗号,最开始的负号(如果有的话)要特判出来

    import java.io.BufferedInputStream;
    import java.util.Scanner;
    ​
    public class PAT1001 {
        public static  void main(String[] args) {
            Scanner scanner = new Scanner(new BufferedInputStream(System.in));
            int a, b;
            a = scanner.nextInt();
            b = scanner.nextInt();
            int c = a + b;
            String s = String.valueOf(c);
            char[] array = s.toCharArray();
            int count = 0;
            String result = "";
            for(int i = array.length - 1; i >= 0; i--) {
                if(array[i] == '-') {
                    result = "-" + result;
                    continue;
                }
                if(count == 3) {
                    result = "," + result;
                    count = 0;
                }
                result = array[i] + result;
                count++;
            }
            System.out.println(result);
        }
    }

    1002 A+B for Polynomials

    用时26分钟

    这题我真的是WA出花了。。。。。。

    整体思路是用木桶,需要注意的点一共有以下几个:

    ①由于数据类型是double,所以在检查木桶中数值是否不为0的时候不能直接和0比较,要和1e-8或者0.1进行比较

    ②在比较的时候要取绝对值,不能直接比较

    ③如果整个多项式的和是0,要注意不能输出“0 ”,必须输出"0"(真要命

    ④每一行的最后一项后面不能跟空格,所以需要用计数器进行特判

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    double barrel[1005];
    using namespace std;
    ​
    double abs(double a) {
        return a > 0? a : -a;
    }
    ​
    int main() {
        int k;
        for(int tt = 0; tt < 2; tt++) {
            cin >> k;
            for(int i = 0 ; i < k; i++) {
                int b;
                scanf("%d", &b);
                double t;
                scanf("%lf", &t);
                barrel[b] += t;
            }
        }
        int cnt = 0;
        for(int i = 1004; i >= 0; i--) {
            if(abs(barrel[i]) >= 0.1) {
                cnt++;
            }
        }
        printf("%d", cnt);
        if(cnt != 0) putchar(' ');
        else return 0;
        int cc = 0;
        for(int i = 1004; i >= 0; i--) {
            if(abs(barrel[i]) >= 0.1) {
                cc++;
                if(cc != cnt)
                    printf("%d %.1lf ", i, barrel[i]);
                else
                    printf("%d %.1lf
    ", i, barrel[i]);
            }
        }
        return 0;
    }

    1003 Emergency

    用时41分钟

    这题是朴素的dijkstra(O(N²)复杂度即可过)(不过需要记录路径数),注意inf一定要开的够大/在比较时对inf进行特判,否则会WA(边权超过了你设定的inf,会在松弛时把inf松弛进去)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define inf 100000000
    #define N 600
    int n,m;
    int dis[N];
    int rescue[N];
    int graph[N][N];            //邻接矩阵
    int pathCount[N];
    int maxRescue[N];
    int done[N];
    ​
    void dijkstra(int s) {
        //朴素dijkstra
        for(int i = 0; i < N; i++) dis[i] = inf;
        dis[s] = 0;
        maxRescue[s] = rescue[s];
        pathCount[s] = 1;
        for(int j = 0; j < n; j++) {
            //共计进行n次
            //找最小值
            int minPos = -1;
            int minValue = inf;
            for(int i = 0;i < n; i++) {
                if(!done[i] && dis[i] < minValue) {
                    minPos = i;
                    minValue = dis[i];
                }
            }
            //cout << "minpos=" << minPos << endl;
            done[minPos] = 1;
            //更新
            for(int i = 0; i < n; i++) {
                if(!done[i] && graph[minPos][i] != inf && dis[i] >= minValue + graph[minPos][i]) {
                    dis[i] = minValue + graph[minPos][i];
                    pathCount[i] += pathCount[minPos];          //记录路径数
                    maxRescue[i] = max(maxRescue[i], rescue[i] + maxRescue[minPos]);    //记录最大rescue值
                }
            }
        }
    ​
    }
    ​
    int main() {
        int s, t;
        cin >> n >> m >> s >> t;
        for(int i = 0; i < n; i++) scanf("%d", &rescue[i]);
        int u,v, w;
        for(int i = 0; i < N ; i++)
            for(int j = 0;j < N; j++)
                graph[i][j] = (i==j)? 0 : inf;
        for(int i = 0; i < m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            if(graph[u][v] > w) {
                graph[u][v] = graph[v][u] = w;
            }
        }
        dijkstra(s);
        printf("%d %d
    ", pathCount[t], maxRescue[t]);
        return 0;
    }
    ​

    1004 Counting Leaves

    用时22分钟

    难得的一次AC(笑哭)

    题意是问一棵树的每一层上有多少个叶子结点,这里涉及到按层遍历,所以整体思路是一个bfs,传统的bfs是用一个单向队列q,但是我们需要知道某一层到哪里结束,这里我使用了另外一个队列qq,来记录每一层的最后一个结点(其实在bfs下,qq队列里最多就只有两个元素,用变量记录就行)。为了方便地获取这一层的节点的最后一个孩子(这一层的节点的最后一个孩子不一定是这一层最后一个节点的孩子,最后一个节点可能没有孩子),我将q从单向队列换成了双向队列,这样我只需要拿最后一个进队的出来,就直接取到这一层的节点的最后一个孩子了。

    #include <iostream>
    #include <queue>
    #include <list>
    #include <vector>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int n, m;
    ​
    vector<int> graph[105];
    bool vis[105];                  //记录这个节点是否是一个叶子结点
    int main() {
        for(int i = 0; i < 105; i++) vis[i] = false;
        cin >> n >> m;
        for(int i = 0; i <m; i++) {
            int u;
            cin >> u;
            int k;
            cin >> k;
            if(k != 0) vis[u] = true;
            for(int j = 0; j < k; j++) {
                int v;
                cin >> v;
                graph[u].push_back(v);
            }
        }
        list<int > q;
        vector<int> vvv;            //用来存放结果
        queue<int> qq;              //用来存放这一层到哪个结点
        q.push_back(1);
        qq.push(1);
        int cnt = 0;
        while(!q.empty()) {
            //bfs
            int u = q.front();
            q.pop_front();
            if(!vis[u]) {
                //这是一个叶子结点,叶子计数器+1
                cnt++;
            } else {
                //这不是一个叶子结点,开始遍历他的所有边
                for(int i = 0; i < graph[u].size(); i++) {
                    //这里是树,所以直接入队就行,不用判是否已经在队列中了,它一定不在队列中
                    q.push_back(graph[u][i]);
                }
            }
            if(u == qq.front()) {
                //这一层的遍历结束了
                vvv.push_back(cnt);
                cnt = 0;
                qq.pop();
                qq.push(q.back());          //最后入队的这个元素就是下一层的结束
            }
        }
        for(int i = 0; i < vvv.size() - 1; i++){
            printf("%d ", vvv[i]);
        }
        printf("%d
    ", vvv[vvv.size()-1]);
        return 0;
    }
     

    1005 Spell It Right

    耗时6分钟

    水题++;

    import java.io.BufferedInputStream;
    import java.util.Scanner;
    ​
    public class PAT1005 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(new BufferedInputStream(System.in));
            String s;
            s = scanner.nextLine();
            char[] array = s.toCharArray();
            int sum = 0;
            for(int i = 0;i < array.length; i++) {
                sum += array[i] - '0';
            }
            s = String.valueOf(sum);
            array = s.toCharArray();
            String[] cons = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
            for(int i = 0; i < array.length - 1; i++) {
                System.out.print(cons[array[i]-'0'] + " ");
            }
            System.out.println(cons[array[array.length-1]-'0']);
        }
    }

    1006 Sign In and Sign Out

    用时10分钟

    按照计算时间戳类似的方式把上班时间和下班时间都转换成统一的int格式(小时*3600+分钟*60+秒钟),然后写两个Comparator,分别把员工id按照两个Comparator进行排序即可,注意两个Comparator一个是升序一个是降序

    (如果用C++实现,就是写两个cmp函数作为sort的参数

    import java.io.BufferedInputStream;
    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Scanner;
    ​
    public class PAT1006 {
        static class Staff {
            String id;
            int timein;
            int timeout;
    ​
            public Staff(String id, int timein, int timeout) {
                this.id = id;
                this.timein = timein;
                this.timeout = timeout;
            }
        }
    ​
        public static class Comparator1 implements Comparator {
    ​
            @Override
            public int compare(Object o1, Object o2) {
                Staff staff1 = (Staff) o1;
                Staff staff2 = (Staff) o2;
                return Integer.compare(staff1.timein, staff2.timein);
            }
        }
    ​
        public static class Comparator2 implements Comparator {
            @Override
            public int compare(Object o1, Object o2) {
                Staff staff1 = (Staff) o1;
                Staff staff2 = (Staff) o2;
                return Integer.compare(staff2.timeout, staff1.timeout);
            }
        }
    ​
        public static void main(String[] args) {
            Scanner scanner = new Scanner(new BufferedInputStream(System.in));
            int n = scanner.nextInt();
            scanner.nextLine();
            List<Staff> list = new ArrayList<>();
            for(int i = 0;i < n; i++) {
                String s = scanner.nextLine();
                String[] array = s.split(" ");
                int timein = 0;
                String[] array2 = array[1].split(":");
                timein = Integer.valueOf(array2[0])*3600+Integer.valueOf(array2[1])*60+Integer.valueOf(array2[2]);
                int timeout = 0;
                array2 = array[2].split(":");
                timeout = Integer.valueOf(array2[0])*3600+Integer.valueOf(array2[1])*60+Integer.valueOf(array2[2]);
                Staff staff = new Staff(array[0], timein, timeout);
                list.add(staff);
            }
            list.sort(new Comparator1());
            System.out.print(list.get(0).id + " ");
            list.sort(new Comparator2());
            System.out.println(list.get(0).id);
        }
    }

    1007 Maximum Subsequence Sum

    用时17分钟

    这个题是允许O(N²)时间的最大子序列,所以……就不必推动态规划式子了,直接前缀和+O(N²)的暴力枚举子数组就a了

    另外要注意题目要求:当所有数字全为负数的时候,要特殊处理(这里我WA了一发:因为0不应该算作负数23333)

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    int a[10005];
    int s[10005];              //前缀和
     int main() {
         int n;
         cin >> n;
         bool flag_negative = true;
         for(int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
            if(a[i] >= 0) flag_negative = false;
            s[i] = (i==0) ? 0 : s[i-1];             //前缀和数组先等于前缀和数组的上一位
            s[i] += a[i];                           //计算前缀和
         }
         if(flag_negative) {
            printf("%d %d %d
    ", 0, a[0], a[n-1]);
         } else {
            int maxValue = -1;
            int left = 0;
            int right = 0;
            for(int i = 0;i < n; i++) {         //枚举起始点(包含
                for(int j = i; j < n ;j++) {      //枚举终止点(包含
                    if(i == 0) {
                        if(s[j] > maxValue) {
                            maxValue = max(maxValue, s[j]), left = a[i], right = a[j];
                        }
                    }
                    else {
                        if(s[j] - s[i-1] > maxValue) {
                            maxValue = max(maxValue, s[j] - s[i-1]), left = a[i], right = a[j];
                        }
                    }
                }
            }
            printf("%d %d %d
    ", maxValue, left, right);
         }
         return 0;
     }

    1008 Elevator

    用时10分钟

    水题

    #include <iostream>
    using namespace std;
    ​
    int main() {
        int location = 0;
        int n;
        int sum = 0;
        cin >> n;
        for(int i = 0; i < n ;i++) {
            int t;
            cin >> t;
            if(location > t) {
                //需要下降
                sum = sum + (location - t) * 4;
            } else if(location < t){
                //需要上升 location < t
                sum += (t - location) * 6;
            }
            location = t;
            sum+= 5;
        }
        cout << sum << endl;
    }
    ​

    1009 Product of Polynomials

    用时:8分钟

    和1002非常像,做完1002再做这个题就轻车熟路了

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    using namespace std;
    double barrel1[1005];
    double barrel2[1005];
    double barrel3[3000];
    ​
    int main() {
        int k;
        cin >> k;
        for(int i = 0; i < k ;i++) {
            int a;
            cin >> a;
            double b;
            cin >> b;
            barrel1[a] += b;
        }
        cin >> k;
        for(int i = 0; i < k ;i++) {
            int a;
            cin >> a;
            double b;
            cin >> b;
            barrel2[a] += b;
        }
        for(int i = 0; i < 1005; i++) {
            if(abs(barrel1[i]) < 1e-8) continue;
            for(int j = 0; j < 1005; j++) {
                if(abs(barrel2[j]) < 1e-8) continue;
                int pos = i + j;
                double value = barrel1[i] * barrel2[j];
                barrel3[pos] += value;
            }
        }
        int cnt = 0;
        for(int i = 2999; i >= 0; i-- ) {
            if(abs(barrel3[i]) > 1e-8) cnt++;
        }
        if(cnt == 0) {
            printf("0
    ");
        } else {
            printf("%d ", cnt);
            int ccc = 0;
            for(int i = 2999; i >= 0; i--) {
                if(abs(barrel3[i]) > 1e-8) {
                    ccc++;
                    if(ccc == cnt) {
                        printf("%d %.1lf
    ", i, barrel3[i]);
                    } else {
                        printf("%d %.1lf ", i, barrel3[i]);
                    }
                }
            }
        }
        return 0;
    }

    1010 Radix

    这题我写了详细题解:https://www.cnblogs.com/Briddle-ch/p/12616754.html

  • 相关阅读:
    协议
    网页制作
    知识点--------二维数组
    方法---------拖延,清屏,前景色,背景色
    小知识点------遍历数组、switch case、do while
    知识点-----------函数
    循环经典--------冒泡排序,查找。
    知识点-------一维数组
    循环语句-----经典案例
    知识点--循环语句
  • 原文地址:https://www.cnblogs.com/Briddle-ch/p/12616799.html
Copyright © 2020-2023  润新知