zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    POJ 3672 水题......
    POJ 3279 枚举?
    STL
    241. Different Ways to Add Parentheses
    282. Expression Add Operators
    169. Majority Element
    Weekly Contest 121
    927. Three Equal Parts
    910. Smallest Range II
    921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/Briddle-ch/p/12616799.html
Copyright © 2011-2022 走看看