第一次参加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. 关于c语言的位运算&,|,^(看懂汉字的都能看懂)

    其中|,&可以当作逻辑运算符,当|,&当成逻辑运算符时,与||,&&的用法基本相似,&&,||运算时会当前面的表达式能够决定整个表达式,则不进行对后面的 ...

  2. codeforces-473D Mahmoud and Ehab and another array construction task (素数筛法+贪心)

    题目传送门 题目大意:先提供一个数组,让你造一个数组,这个数组的要求是 1 各元素之间都互质  2  字典序大于等于原数组  3 每一个元素都大于2 思路: 1.两个数互质的意思就是没有公因子.所以每 ...

  3. 10.Spring集成一

    1.Email 电子邮件工作原理: 邮件发送方通过邮件发送客户端把邮件发送到发送方的邮件服务器,在发送的过程中需要用到SMTP协议发送方的邮件服务器把邮件发送到接收方的邮件服务器,使用的协议也是SMT ...

  4. Filter责任链模式

    Filter责任链的创建 org.apache.catalina.core.ApplicationFilterFactory#createFilterChain,  此方法是被org.apache.c ...

  5. 风险识别工具 - 影响图(Influence Diagram)

    原文地址:http://blog.csdn.net/jameszhou/archive/2007/06/24/1664494.aspx PMBOK(2004 3rd 英) P248关于风险识别的图形技 ...

  6. 如何获取Android手机的唯一标识

    有很多场景和需求你需要用到手机设备的唯一标识符. 在Android中,有以下几种方法获取这样的ID. 1. The IMEI: 仅仅只对Android手机有效: 1 2 TelephonyManage ...

  7. javascript Array数组详解 各种方法

    1.数组的声明方法(1): arrayObj = new Array(); //创建一个数组.复制代码 代码如下: var arr1 = new Array(); (2):arrayObj = new ...

  8. 【3dsMax安装失败,如何卸载、安装3dMax 2019?】

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

  9. 第8章 IO类

    8.1 IO类 iostream                    istream, wistream从流中读取数据 ostream, wostream iostream, wiostream读写 ...

  10. php 自带加密、解密函数

    php 自带的加密函数  不可逆的加密函数为:md5().crypt() md5() 用来计算 MD5 哈稀.语法为:string md5(string str); crypt() 将字符串用 UNI ...