【算法】【PAT】1081-1090

这篇博客详细介绍了PAT甲级算法竞赛中的1081到1090题,涵盖题目描述、解题分析及C++实现。涉及知识点包括模拟、树遍历、最短路径、排序算法等,适合提高编程技能和算法理解。
摘要由CSDN通过智能技术生成

点击前往【PAT甲级之路总纲】

1081 Rational Sum (20分)

题目

在这里插入图片描述Sample Input 1:

5
2/5 4/15 1/30 -2/60 8/3

Sample Output 1:

3 1/3

Sample Input 2:

2
4/3 2/3

Sample Output 2:

2

Sample Input 3:

3
1/3 -1/6 1/8

Sample Output 3:

7/24

题解

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

long long gcd(long long a, long long b) {
	return b == 0 ? abs(a) : gcd(b, a%b);
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("data.txt", "r", stdin);
#endif

	long long n, a, b, suma = 0, sumb = 1, gcdvalue;
	scanf("%lld", &n);
	for (int i = 0; i < n; ++i) {
		scanf("%lld/%lld", &a, &b);
		gcdvalue = gcd(a, b);
		a = a / gcdvalue;
		b = b / gcdvalue;
		suma = a * sumb + suma *b;
		sumb = b * sumb;
		gcdvalue = gcd(suma, sumb);
		suma /= gcdvalue;
		sumb /= gcdvalue;
	}
	long long integer = suma / sumb;
	suma = suma - (sumb * integer);
	if (integer != 0) {
		printf("%lld", integer);
		if (suma != 0) printf(" ");
	}
	if (suma != 0)
		printf("%lld/%lld", suma, sumb);
	if (integer == 0 && suma == 0)
		printf("0");
	return 0;
}

1082 Read Number in Chinese (25分) 推荐:1星

题目

在这里插入图片描述Sample Input 1:

-123456789

Sample Output 1:

Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu

Sample Input 2:

100800

Sample Output 2:

yi Shi Wan ling ba Bai

分析

推荐:1星
模拟题,重点在输出 “ling"的条件判断。

题解

#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

string num[10] = { "ling","yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu" };
string c[6] = { "Ge","Shi", "Bai", "Qian", "Yi", "Wan" };
int J[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
vector<string> res;

int main() {
#ifndef ONLINE_JUDGE
	freopen("data.txt", "r", stdin);
#endif
	int n;
	cin >> n;
	if (n == 0) {
		cout << "ling";
		return 0;
	}
	if (n < 0) {
		cout << "Fu ";
		n = -n;
	}
	int part[3];
	part[0] = n / 100000000;
	part[1] = (n % 100000000) / 10000;
	part[2] = n % 10000;
	bool zero = false; //是否在非零数字前输出合适的ling
	int printCnt = 0; //用于维护单词前没有空格,之后输入的单词都在前面加一个空格。
	for (int i = 0; i < 3; i++) {
		int temp = part[i]; //三个部分,每部分内部的命名规则都一样,都是X千X百X十X
		for (int j = 3; j >= 0; j--) {
			int curPos = 8 - i * 4 + j; //当前数字的位置
			if (curPos >= 9) continue; //最多九位数
			int cur = (temp / J[j]) % 10;//取出当前数字
			if (cur != 0) {
				if (zero) {
					printCnt++ == 0 ? cout << "ling" : cout << " ling";
					zero = false;
				}
				if (j == 0)
					printCnt++ == 0 ? cout << num[cur] : cout << ' ' << num[cur]; //在个位,直接输出
				else
					printCnt++ == 0 ? cout << num[cur] << ' ' << c[j] : cout << ' ' << num[cur] << ' ' << c[j]; //在其他位,还要输出十百千
			}
			else {
				if (!zero&&j != 0 && n / J[curPos] >= 10) zero = true;   //注意100020这样的情况
			}
		}
		if (i != 2 && part[i]>0) cout << ' ' << c[i + 4]; //处理完每部分之后,最后输出单位,Yi/Wan
	}
	return 0;
}

1083 List Grades (25分)

题目

在这里插入图片描述Sample Input 1:

4
Tom CS000001 59
Joe Math990112 89
Mike CS991301 100
Mary EE990830 95
60 100

Sample Output 1:

Mike CS991301
Mary EE990830
Joe Math990112

Sample Input 2:

2
Jean AA980920 60
Ann CS01 80
90 95

Sample Output 2:

NONE

分析

模拟题

题解

#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct stu {
	char name[12];
	char id[12];
	int grade;
};

bool cmp1(stu a, stu b) {
	return a.grade > b.grade;
}

int main() {
#ifdef ONLINE_JUDGE
#else
	freopen("data.txt", "r", stdin);
#endif //  ONLINE_JUDGE
	int n, low, high, cnt = 0;
	scanf("%d", &n);
	vector<stu> v(n);
	for (int i = 0; i < n; ++i) {
		scanf("%s %s %d", v[i].name, v[i].id, &v[i].grade);
	}
	scanf("%d %d", &low, &high);
	for (int i = 0; i < n; ++i) {
		if (v[i].grade < low || v[i].grade > high) {
			v[i].grade = -1;
		}
		else {
			++cnt;
		}
	}
	sort(v.begin(), v.end(), cmp1);
	for (int i = 0; i < cnt; ++i) {
		printf("%s %s\n", v[i].name, v[i].id);
	}
	if (cnt == 0) {
		printf("NONE");
	}
	return 0;
}

1084 Broken Keyboard (20分)

题目

在这里插入图片描述Sample Input:

7_This_is_a_test
_hs_s_a_es

Sample Output:

7TI

分析

利用STL库可以更快地写出你的代码,当然只要能解出来,用什么都行。

题解

使用stl

#include <iostream>
#include <cctype>
using namespace std;
int main() {
#ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
#endif // ONLINE_JUDGE
    string s1, s2, ans;
    cin >> s1 >> s2;
    for (int i = 0; i < s1.length(); i++)
        if (s2.find(s1[i]) == string::npos && ans.find(toupper(s1[i])) == string::npos)
            ans += toupper(s1[i]);
    cout << ans;
    return 0;
}

不使用std(打表)

#include <iostream>
#include <string>
#include <string.h>
using namespace std;
bool book[256];
int main(){
#ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
#endif // ONLINE_JUDGE
    string s1, s2;
    cin >> s1 >> s2;
    for(int i = 0; i < s2.length(); i++) book[toupper(s2[i])] = true;
    for(int i = 0; i < s1.length(); i++){
        char t = toupper(s1[i]);
        if(!book[t]){
            book[t] = true;
            printf("%c", t);
        }
    }
    return 0;
}

1085 Perfect Sequence (25分)

题目

在这里插入图片描述Sample Input:

10 8
2 3 20 4 5 1 6 7 8 9

Sample Output:

8

分析

这道题目看似平平无奇,事实上隐藏着一个剪枝的小技巧,如果不进行只是使用循环的话,可能会超时。

要点

转换下思路,利用前面的结果来剪枝,先进行排序,使用result来保存之前最长的长度,后面就可以直接从i+result开始,跳过result个之前比较过的值。

知识点

  • 使用尽可能多的数组成符合 M < N * q的数组
  • N是最小,M是最大

题解

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
    int n;
    long long p;
    scanf("%d%lld", &n, &p);
    vector<int> v(n);
    for (int i = 0; i < n; i++)
        cin >> v[i];
    sort(v.begin(), v.end()); ///对顺序没要求就应该先排序
    int result = 0, temp = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + result; j < n; j++) {
            if (v[j] <= v[i] * p) {
                temp = j - i + 1;
                if (temp > result) ///result
                    result = temp;
            } else {
                break;
            }
        }
    }
    cout << result;
    return 0;
}

1086 Tree Traversals Again (25分) 推荐指数:1星

题目

在这里插入图片描述Sample Input:

6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:

3 4 2 6 5 1

分析

题目给人的感觉似乎是要做一道模拟堆栈的题,但是,你要是这么做,就too young too simple了,实际上,这是一道前序+中序得后序的题目。有前序来提供root节点,由中序来划分左右

要点

  • 前序,中序数组转后序 : 注意到前序的存在很关键
  • 模拟栈处理

题解

#include <cstdio> ///等价于stdio.h
#include <vector>
#include <stack>
#include <cstring>
using namespace std;
vector<int> pre, in, post,value; ///数组中保留的是下标
void postorder(int root, int start, int end) { ///后序排列
    if (start > end) return;
    int i = start;
    while (i < end && in[i] != pre[root]) i++;
    postorder(root + 1, start, i - 1);
    postorder(root + 1 + i - start, i + 1, end);
    post.push_back(pre[root]);
}
int main() {
    int n;
    scanf("%d", &n);
    char str[5];
    stack<int> s;
    int key=0;
    while (~scanf("%s", str)) { ///遍历数组,并生成inorder的数组
        if (strlen(str) == 4) {
            int num;
            scanf("%d", &num);
            value.push_back(num);
            pre.push_back(key);
            s.push(key++);
        } else {
            in.push_back(s.top());
            s.pop();
        }
    }
    postorder(0, 0, n - 1);
    printf("%d", value[post[0]]);
    for (int i = 1; i < n; i++)
        printf(" %d",value[post[i]]);
    return 0;
}

1087 All Roads Lead to Rome (30分) 推荐:★

题目

在这里插入图片描述Sample Input:

6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1

Sample Output:

3 3 195 97
HZH->PRS->ROM

分析

这种题型的重要性不用多说,再来巩固一下吧。
注意查找路径得通过dfs,在抵达目标后进行一些决策即可判断。

知识点

  • 最短路径问题
  • 深度搜索
  • 模拟
  • 名称映射

题解

#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
int n, k;
const int inf = 999999999;
int e[205][205], weight[205], dis[205];
bool visit[205];
vector<int> pre[205], temppath, path;
map<string, int> m;
map<int, string> m2;
int maxvalue = 0, mindepth, cntpath = 0;
double maxavg;
void dfs(int v) { ///当前点进入路径
    temppath.push_back(v);
    if(v == 1) {
        int value = 0;
        for(int i = 0; i < temppath.size(); i++) {
            value += weight[temppath[i]];
        }
        double tempavg = 1.0 * value / (temppath.size() - 1);
        if(value > maxvalue) {
            maxvalue = value;
            maxavg = tempavg;
            path = temppath;
        } else if(value == maxvalue && tempavg > maxavg) {
            maxavg = tempavg;
            path = temppath;
        }
        temppath.pop_back();
        cntpath++;
        return ;
    }
    for(int i = 0; i < pre[v].size(); i++) {
        dfs(pre[v][i]);
    }
    temppath.pop_back();
}
int main() {
    fill(e[0], e[0] + 205 * 205, inf);
    fill(dis, dis + 205, inf);
    scanf("%d %d", &n, &k);
    string s;
    cin >> s;
    m[s] = 1;/// 1 : 目的城市
    m2[1] = s;
    for(int i = 1; i < n; i++) { 
        cin >> s >> weight[i+1];
        m[s] = i+1;
        m2[i+1] = s;
    }
    string sa, sb;
    int temp;
    for(int i = 0; i < k; i++) {
        cin >> sa >> sb >> temp;
        e[m[sa]][m[sb]] = temp;
        e[m[sb]][m[sa]] = temp;
    }
    dis[1] = 0;
    for(int i = 0; i < n; i++) {
        int u = -1, minn = inf;
        for(int j = 1; j <= n; j++) {
            if(visit[j] == false && dis[j] < minn) {
                u = j;
                minn = dis[j];
            }
        }
        if(u == -1) break;
        visit[u] = true;
        for(int v = 1; v <= n; v++) {  ///第一遍遍历
            if(visit[v] == false && e[u][v] != inf) {
                if(dis[u] + e[u][v] < dis[v]) {
                    dis[v] = dis[u] + e[u][v];
                    pre[v].clear();
                    pre[v].push_back(u);
                } else if(dis[v] == dis[u] + e[u][v]) {
                    pre[v].push_back(u);
                }
            }
        }
    }
    int rom = m["ROM"];
    dfs(rom); ///从后往前
    printf("%d %d %d %d\n", cntpath, dis[rom], maxvalue, (int)maxavg);
    for(int i = path.size() - 1; i >= 1; i--) { ///反向输出
        cout << m2[path[i]] << "->";
    }
    cout << "ROM";
    return 0;
}

1088 Rational Arithmetic (20分) 推荐:★

题目

在这里插入图片描述Sample Input 1:

2/3 -4/2

Sample Output 1:

2/3 + (-2) = (-1 1/3)
2/3 - (-2) = 2 2/3
2/3 * (-2) = (-1 1/3)
2/3 / (-2) = (-1/3)

Sample Input 2:

5/3 0/6

Sample Output 2:

1 2/3 + 0 = 1 2/3
1 2/3 - 0 = 1 2/3
1 2/3 * 0 = 0
1 2/3 / 0 = Inf

分析

涉及到整型的运算,注意使用longlong类型的数据

  • 很多的小细节
  • 找最小公约数

题解

#include <iostream>
#include <cmath>
using namespace std;
long long a, b, c, d;
long long gcd(long long t1, long long t2) { ///先找最小公约数
    return t2 == 0 ? t1 : gcd(t2, t1 % t2);
}
void func(long long m, long long n) { ///利用这个来输出单个数,最小粒度,最快实现
    if (m * n == 0) {
        printf("%s", n == 0 ? "Inf" : "0");
        return ;
    }
    bool flag = ((m < 0 && n > 0) || (m > 0 && n < 0));
    m = abs(m); n = abs(n);
    long long x = m / n;
    printf("%s", flag ? "(-" : "");
    if (x != 0) printf("%lld", x);
    if (m % n == 0) {
        if(flag) printf(")");
        return ;
    }
    if (x != 0) printf(" ");
    m = m - x * n;
    long long t = gcd(m, n);
    m = m / t; n = n / t;
    printf("%lld/%lld%s", m, n, flag ? ")" : "");
}
int main() {
    scanf("%lld/%lld %lld/%lld", &a, &b, &c, &d);
    func(a, b); printf(" + "); func(c, d); printf(" = "); func(a * d + b * c, b * d); printf("\n");
    func(a, b); printf(" - "); func(c, d); printf(" = "); func(a * d - b * c, b * d); printf("\n");
    func(a, b); printf(" * "); func(c, d); printf(" = "); func(a * c, b * d); printf("\n");
    func(a, b); printf(" / "); func(c, d); printf(" = "); func(a * d, b * c);
    return 0;
}

1089 Insert or Merge (25分) ★★★

题目

在这里插入图片描述Sample Input 1:

10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0

Sample Output 1:

Insertion Sort
1 2 3 5 7 8 9 4 6 0

Sample Input 2:

10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6

Sample Output 2:

Merge Sort
1 2 3 8 4 5 7 9 0 6

分析

插入排序:
分块排序:很有意思k*2思路,要点多多,十分有趣
排序一些技巧
注意分部的时候:i < n/k

题解

判断是插入排序还是合并排序,并返回下一次操作后的值

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    int n, a[100], b[100], i, j;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i]; ///原始数组
    for (int i = 0; i < n; i++)
        cin >> b[i]; ///部分排序数组
    for (i = 0; i < n - 1 && b[i] <= b[i + 1]; i++); ///获取部分排序数组的有序部分
    for (j = i + 1; a[j] == b[j] && j < n; j++); ///判断无序部分相同的位置
    if (j == n) { ///与数组长度相同
        cout << "Insertion Sort" << endl; ///插入排序
        sort(a, a + i + 2);  ///左开右闭,返回下一次排序的结果,即排序到 i+1位置
    } else {
        cout << "Merge Sort" << endl; ///合并排序
        int k = 1, flag = 1;
        while(flag) { /// 一步步排序,直到完全相等
            flag = 0;
            for (i = 0; i < n; i++) {
                if (a[i] != b[i])
                    flag = 1;
            }
            k = k * 2;
            for (i = 0; i < n / k; i++)
                sort(a + i * k, a + (i + 1) * k); ///使用sort来代劳
            sort(a + n / k * k, a + n);
        }
    }
    for (j = 0; j < n; j++) {
        if (j != 0) printf(" ");
        printf("%d", a[j]);
    }
    return 0;
}

1090 Highest Price in Supply Chain (25分)

题目

在这里插入图片描述Sample Input:

9 1.80 1.00
1 5 4 4 -1 4 5 3 6

Sample Output:

1.85 2

分析

奔溃先找输入

题解

与上一个相似,但也做了些更改

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
int n, maxdepth = 0, maxnum = 0, temp, root;
vector<int> v[100010];
void dfs(int index, int depth) { ///深度搜索
    if(v[index].size() == 0) {
        if(maxdepth == depth)
            maxnum++;
        if(maxdepth < depth) {
            maxdepth = depth;
            maxnum = 1;
        }
        return ;
    }
    for(int i = 0; i < v[index].size(); i++)
        dfs(v[index][i], depth + 1);
}
int main() {
    double p, r;
    scanf("%d %lf %lf", &n, &p, &r);
    for(int i = 0; i < n; i++) {
        scanf("%d", &temp);
        if(temp == -1)
            root = i;
        else
            v[temp].push_back(i);
    }
    dfs(root, 0);
    printf("%.2f %d", p * pow(1 + r/100, maxdepth), maxnum);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值