第一次参加pat考试,结果很惨,只做了中间两道题,还有一个测试点错误,所以最终只得了不到50分。题目是甲级练习题的1148-1151。

考试时有些紧张,第一题第二题开始测试样例都运行不正确,但是调试程序考场的vs2013不能粘贴,还得一点点输上去。浪费了很多时间。

1、Werewolf - Simple Version

之前遇到这种题目较少,所以刚开始没什么思路。后来想到的方法是假设撒谎的两个人分别是i、j,然后遍历所有i、j,找出符合条件的。当时总共用了得有一个小时,但程序一直得不到正确答案,只好放弃。后来回到学校去调试程序发现问题出现在一个continue上,continue后面有一个操作需要完成但直接跳过了。但是按这个方法最后一个测试点错误。

其实这类题目问的是什么就假设什么,然后遍历所有可能性找出符合条件的就行。因此正确做法是直接假设两个狼人为i、j就行。

 #include <iostream>
using namespace std; int a[], N;
int main()
{
int i, j, k, t;
cin >> N;
for (i = ; i <= N; i++) cin >> a[i];
for (i = ; i <= N; i++)
{
for (j = i + ; j <= N; j++)
{
bool b[] = {};
b[i] = b[j] = ;
int lie1, lie2, cnt = ;
for (k = ; k <= N; k++)
{
if (a[k] > && b[a[k]] || a[k] < && !b[-a[k]])
{
cnt++;
if (cnt == ) lie1 = k;
if (cnt == ) lie2 = k;
}
}
if (cnt == && b[lie1] != b[lie2])
{
printf("%d %d", i, j);
return ;
}
}
}
printf("No Solution");
return ;
}

2、Dangerous Goods Packaging

这道题比较简单,但是考试时一开始思路不对,我用的是一个数组保存每一个编号不能放到一块的编号。但是每一个编号可能和多个编号不能放到一块,因此用set存储每一个编号的互斥编号。

 #include <iostream>
#include <map>
#include <set>
using namespace std; int main()
{
int N, M;
cin >> N >> M;
map<int, set<int>> mp;
int i, a, b;
for (i = ; i < N; i++)
{
cin >> a >> b;
mp[a].insert(b);
mp[b].insert(a);
}
int K, j;
for (i = ; i < M; i++)
{
cin >> K;
set<int> st;
bool flag = true;
for (j = ; j < K; j++)
{
cin >> a;
if (!flag) continue;
if (mp.find(a) != mp.end())
{
for (int t : mp[a])
{
if (st.find(t) != st.end()) flag = false;
}
}
st.insert(a);
}
printf("%s\n", flag ? "Yes" : "No");
}
return ;
}

3、Travelling Salesman Problem

这道题也不难,但是考试时有一个测试点错误,回学校后再看时发现是判断时少了一个条件,即TS cycle和TS simple cycle都要经过所有顶点。

当路径上有不相邻的顶点或者路径的首尾顶点不相连或不经过所有顶点时,Not a TS cycle。否则路径上除了最后一个顶点外有重复的顶点就是TS cycle,否则就是TS simple cycle。

 #include <iostream>
using namespace std; int G[][]; int main()
{
int N, M;
cin >> N >> M;
int v, w, d, i;
for (i = ; i < M; i++)
{
cin >> v >> w >> d;
G[v][w] = G[w][v] = d;
}
int K, n, j, first, minId, min = ;
cin >> K;
for (i = ; i <= K; i++)
{
bool na = false, simple = true, allOccured = true;
bool occur[] = {};
int sum = ;
cin >> n >> first;
v = first;
occur[first] = true;
for (j = ; j < n; j++)
{
cin >> w;
sum += G[v][w];
if (G[v][w] == ) na = true;
if (occur[w] && j != n - ) simple = false;
occur[w] = true;
v = w;
}
for (j = ; j <= N; j++)
{
if (!occur[j]) allOccured = false;
}
printf("Path %d: ", i);
if (na) printf("NA ");
else printf("%d ", sum);
if (v != first || na || !allOccured) printf("(Not a TS cycle)\n");
else
{
if (simple) printf("(TS simple cycle)\n");
else printf("(TS cycle)\n");
if (sum < min)
{
min = sum;
minId = i;
}
}
}
printf("Shortest Dist(%d) = %d", minId, min);
return ;
}

4、LCA in a Binary Tree

这道题开始一看还以为是原题,就按照二叉搜索树去做,最后运行结果不正确才发现题目说的是二叉树,不是二叉搜索树。但已经没时间了。

后来我用的方法是,先建树,然后求出顶点到两个节点的路径,把两个路径从前往后比较,第一个不相同结点的前一个结点就是LCA。

 #include <iostream>
#include <set>
#include <vector>
using namespace std; typedef struct Node *Tree;
struct Node
{
int data;
Tree left, right;
}*root; vector<int> in, pre;
Tree buildTree(Tree T, int begin, int end, int root);
int ancestor(int u, int v);
bool path(Tree T, int a, vector<int>& v); int main()
{
int M, N, i;
cin >> M >> N;
in.resize(N);
pre.resize(N);
set<int> st;
for (i = ; i < N; i++) cin >> in[i];
for (i = ; i < N; i++)
{
cin >> pre[i];
st.insert(pre[i]);
}
root = NULL;
root = buildTree(root, , N - , );
int u, v;
for (i = ; i < M; i++)
{
cin >> u >> v;
bool b1 = (st.find(u) == st.end());
bool b2 = (st.find(v) == st.end());
if (b1 && b2) printf("ERROR: %d and %d are not found.", u, v);
else if (b1 || b2) printf("ERROR: %d is not found.", b1 ? u : v);
else {
int anc = ancestor(u, v);
if (anc == u) printf("%d is an ancestor of %d.", u, v);
else if (anc == v) printf("%d is an ancestor of %d.", v, u);
else printf("LCA of %d and %d is %d.", u, v, anc);
}
printf("\n");
}
return ;
} Tree buildTree(Tree T, int begin, int end, int root)
{
if (begin > end) return NULL;
T = new Node;
T->data = pre[root];
T->left = T->right = NULL;
int p;
for (p = begin; p <= end; p++)
{
if (in[p] == pre[root]) break;
}
T->left = buildTree(T->left, begin, p - , root + );
T->right = buildTree(T->right, p + , end, root + p - begin + );
return T;
} int ancestor(int u, int v)
{
vector<int> p1, p2;
bool b1 = path(root, u, p1);
bool b2 = path(root, v, p2);
int i;
for (i = ; i < p1.size() && i < p2.size() && p1[i] == p2[i]; i++);
if (i == p1.size()) return p1[i - ];
if (i == p2.size()) return p2[i - ];
return p1[i - ];
} bool path(Tree T, int a, vector<int>& v)
{
if (T == NULL) return false;
v.push_back(T->data);
if (T->data == a) return true;
bool b1 = path(T->left, a, v);
if (b1) return true;
bool b2 = path(T->right, a, v);
if (!b1 && !b2)
{
v.pop_back();
return false;
}
return true;
}

看柳婼的博客学会了较简单的方法:先把每个结点在中序遍历中的位置记录下来,然后递归时根据u,v和当前root在中序遍历中的位置就可以知道u和v是在当前结点左子树还是右子树。

 #include <iostream>
#include <map>
#include <vector>
using namespace std; vector<int> in, pre;
map<int, int> mp; void lca(int left, int right, int root, int u, int v); int main()
{
int M, N, i;
cin >> M >> N;
in.resize(N + );
pre.resize(N + );
for (i = ; i <= N; i++)
{
cin >> in[i];
mp[in[i]] = i;
}
for (i = ; i <= N; i++) cin >> pre[i];
int u, v;
for (i = ; i < M; i++)
{
cin >> u >> v;
if (mp[u] == && mp[v] == ) printf("ERROR: %d and %d are not found.\n", u, v);
else if (mp[u] == || mp[v] == ) printf("ERROR: %d is not found.\n", mp[u] ? v : u);
else lca(, N, , u, v);
}
return ;
} void lca(int left, int right, int root, int u, int v)
{
if (left > right) return;
int pU = mp[u], pV = mp[v], pRoot = mp[pre[root]];
if (pU < pRoot && pV < pRoot)
lca(left, pRoot - , root + , u, v);
else if (pU < pRoot && pV > pRoot || pU > pRoot && pV < pRoot)
printf("LCA of %d and %d is %d.\n", u, v, pre[root]);
else if (pU > pRoot && pV > pRoot)
lca(pRoot + , right, root + pRoot - left + , u, v);
else if (pU == pRoot)
printf("%d is an ancestor of %d.\n", u, v);
else if (pV == pRoot)
printf("%d is an ancestor of %d.\n", v, u);
}

参加这次考试只能说明自己很菜,解题速度比较慢;审题不仔细,比如第二题开始用的一个数组去存储每个编号的互斥编号;写代码容易出现很多问题,比如第一题continue导致逻辑出现错误。

正在准备考研,时间很紧张,只能周末抽时间刷几道题,12月份冬季再参加一次。

更新:

求LCA时,用set来判断节点是否存在,当两节点都存在时,可用leetcode中的较简单的的方法:

 #include <iostream>
#include <vector>
#include <set>
using namespace std; struct Node {
int val;
Node *left, *right;
Node(int v) : val(v), left(NULL), right(NULL) {}
}*root; vector<int> in, pre;
int U, V; void buildTree(Node* &root, int b1, int b2, int e2) {
if (b2 > e2) return;
int p, t = pre[b1];
root = new Node(t);
for (p = b2; p <= e2 && in[p] != t; p++);
buildTree(root->left, b1 + , b2, p - );
buildTree(root->right, b1 + p - b2 + , p + , e2);
} Node* lca(Node* root) {
if (root == NULL || root->val == U || root->val == V)
return root;
Node* l = lca(root->left);
Node* r = lca(root->right);
if (l && r) return root;
if (l) return l;
return r;
} int main() {
int M, N, i;
cin >> M >> N;
set<int> st;
in.resize(N); pre.resize(N);
for (i = ; i < N; i++) {
cin >> in[i];
st.insert(in[i]);
}
for (i = ; i < N; i++) cin >> pre[i];
buildTree(root, , , N - );
for (i = ; i < M; i++) {
cin >> U >> V;
bool b1 = (st.find(U) != st.end());
bool b2 = (st.find(V) != st.end());
if (b1 && b2) {
Node* T = lca(root);
if (T->val == U) printf("%d is an ancestor of %d.", U, V);
else if (T->val == V) printf("%d is an ancestor of %d.", V, U);
else printf("LCA of %d and %d is %d.", U, V, T->val);
}
else if (!b1 && !b2)
printf("ERROR: %d and %d are not found.", U, V);
else if (!b1)
printf("ERROR: %d is not found.", U);
else
printf("ERROR: %d is not found.", V);
printf("\n");
}
return ;
}

2018.9.8pat秋季甲级考试的更多相关文章

  1. 2021.9.12周六PAT甲级考试复盘与总结

    周六PAT甲级考试复盘与总结 先说结论:仍未步入"高手"行列:现在的学习节奏与方法是对的,有十万分的必要坚持下去. 题目 知识点 分数 T1 前缀和.二分 11 / 20 T2 排 ...

  2. pat甲级考试+pat1051+1056

    同上一篇博客: 贪心题目我已经刷了将近30道了,由于那几天考驾照就没写,以后有空的时候补过来吧,都在codeblock里 pat的题也刷了点,acwing 的题也刷了点,基本都攒下了.以后也会慢慢补过 ...

  3. 2018.3 江苏省计算机等级考试 C语言 编程题答案

    题目要求:给定一个数字范围,输出满足这些条件: 1.能被3整除: 2.包含数字5, 将满足的数字放在特定的数组里输出.输出这些数里5出现的个数.数字的个数. 想起来有点伤心,本来很简单的题,考试的时候 ...

  4. 2019年春PAT甲级考试

    这次考试不是很理想,一道题目没能做完. 自己原因差不多三条: 1.自己实力不够,准备时间也有点仓促,自己没能做到每道题目都有清晰的思路. 2.考试的心理素质不行,因为设备原因东奔西跑浪费了挺多时间,自 ...

  5. 2019秋季PAT甲级_备考总结

    2019 秋季 PAT 甲级 备考总结 在 2019/9/8 的 PAT 甲级考试中拿到了满分,考试题目的C++题解记录在这里,此处对备考过程和考试情况做一个总结.如果我的方法能帮助到碰巧点进来的有缘 ...

  6. PAT甲级满分有感

    时间轴: 2017年,数据结构加入了我的课程清单. 2018年12月,我从网易云课堂下载了数据结构的所有课程视频(学校里没有网,只能离线看),开始一刷.一刷只看了视频,基本没有做题,看到AVL树的时候 ...

  7. 浙江大学计算机程序设计能力考试(PAT)简介

    计算机程序设计能力考试(Programming Ability Test,简称 PAT)旨在通过统一组织的在线考试及自动评测方法客观地评判考生的算法设计与程序设计实现能力,科学地评价计算机程序设计人才 ...

  8. Before NOIP 2018

    目录 总结 刷题 2018 - 9 - 24 2018 - 9 - 25 2018 - 9 - 26 2018 - 9 - 27 2018 - 9 - 28 2018 - 9 - 29 2018 - ...

  9. 超全面!UI设计师如何适配2018新款iPhone

    北京时间9月13日凌晨1点,苹果在美国加利福尼亚州的Apple Park园区召开了2018年苹果秋季新品发布会. 很多人对这次科技界的春晚充满了期待,除了那些让人“剁手”的新品,设计师关注的还有新手机 ...

随机推荐

  1. P2264 情书

    传送门 正常会想到字典树 然鹅数据怎么小直接map也能过 然后就写map暴力匹配了 毫无思维难度,毫无代码难度 注意逗号算单词分隔符,如果有句号就算另一句 同一句的单词重复出现只计算一次贡献 再开个m ...

  2. xlrd和xlwd模块

    xlrd模块 是python中一个第三方的用于读取excle表格的模块 exlce结构分析 一个excle表格包含多个sheet 一个sheet中包含多行多列 每个单元格具备唯一的行号和列号 常用函数 ...

  3. Spring里的Ant Pattern

    Spring里的Ant Pattern用于匹配URL 可以参考官网:https://docs.spring.io/spring/docs/current/javadoc-api/org/springf ...

  4. Subarray Sum K

    Given an nonnegative integer array, find a subarray where the sum of numbers is k. Your code should ...

  5. 单例模式+volatile禁止指令重排序

    单例模式: 单例,顾名思义就是只能有一个.不能再出现第二个.就如同地球上没有两片一模一样的树叶一样. 在这里就是说:一个类只能有一个实例,并且整个项目系统都能访问该实例. 单例模式共分为两大类: 懒汉 ...

  6. 使用PIE对IE6、7、8进行CSS3兼容介绍和经验总结

    下面说说如何对 IE10 以下版本的浏览器进行部分 CSS3 兼容 国外团队开发的兼容插件,去年做项目时才发现,非常强大 主角:PIE.js ,  PIE.htc    两种方法可以实现 官方网站:h ...

  7. inventor安装错误

    AUTODESK系列软件着实令人头疼,安装失败之后不能完全卸载!!!(比如maya,cad,3dsmax等).有时手动删除注册表重装之后还是会出现各种问题,每个版本的C++Runtime和.NET f ...

  8. 虚拟机扩容(/dev/mapper/centos-root 空间不足)

    1:.首先查看我们的根分区大小是多少 df -h 文件系统                类型      容量  已用  可用 已用% 挂载点 /dev/mapper/centos-root xfs  ...

  9. 修改mysql表的字符集

    ALTER TABLE logtest CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci; 修改数据库字符集: 代码如下: ALTER DAT ...

  10. [巩固C#] 一、特性是什么东东

    阅读目录   关闭   前言 特性是什么? 那么什么是“元数据”? 特性到底是什么? 我们自定义一个特性玩玩 什么是命名参数? 我们来继续要看看AttributeUsage(这个描... 自定义特性可 ...