第一次参加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 ;
}

最新文章

  1. 怎样从C#中打开数据库并进行 增 删 改 查 操作
  2. ASP.NET WebAPI 03 返回结果
  3. python实现文章或博客的自动摘要(附java版开源项目)
  4. 技巧分享——如何去除多余的CSS代码?
  5. delete之后千万要记得将指针置空,即勿重复delete!!!
  6. Python笔记(二)
  7. Html5页面返回机制解决方案
  8. postgresql----serial类型和序列
  9. Python3.x 配置原生虚拟环境
  10. SSIS-导入Excel文件时记录行号
  11. 管道及I/O重定向
  12. zabbix自动注册
  13. js对象的深拷贝
  14. 20165227《网络对抗技术》Exp0 Kali安装 Week1
  15. Hue中hive(hive cli)查询结果中显示列名,不带表名
  16. 在centos上搭建JavaWeb环境(jdk+mysql+tomcat)
  17. 浅谈对NaN的理解
  18. [Java学习] java泛型通配符和类型参数的范围
  19. C++指针与引用
  20. matlab快捷键大全

热门文章

  1. P2421 [NOI2002]荒岛野人
  2. HDU 4507 求指定范围内与7不沾边的所有数的平方和 (数位DP)
  3. java中检测网络是否相通
  4. Dev Express Report 学习总结(四)Dev Express 动态生成XRTable使用总结
  5. JobService 7.0 定时任务不生效
  6. jquery 操作 checkbox select
  7. Unity 游戏对象的组件列表
  8. PlayMaker 做成预制体
  9. firefox插件-自动化测试工具-selenium IDE
  10. aspx页面导出为word