├── .DS_Store ├── 2018.12.9 PAT 甲级冬考小结.md ├── C++11_STL_CheatSheet ├── .DS_Store ├── DemoCode │ ├── .DS_Store │ └── Graph_BFS_DFS.cpp ├── README.md └── STLimg │ ├── .DS_Store │ ├── AVLInsertCode.png │ ├── AVLRotation.png │ ├── ChangeVal.jpeg │ ├── ContainerwithIt.jpeg │ ├── DeleteVal.jpeg │ ├── Dijkstra.png │ ├── LL.png │ ├── LR.png │ ├── ListIt.jpeg │ ├── ListMFuncs.jpeg │ ├── NotChangeOrder.jpeg │ ├── OperateOrdered.jpeg │ ├── RotationSum.png │ ├── Sort.jpeg │ ├── changeOrder.jpeg │ ├── iterator.png │ └── preOrderAndinOrder.png ├── PAT真题After算法笔记 ├── 1156-1159题目.docx ├── A1156_Sexy Primes.cpp ├── A1157_Anniversary.cpp ├── A1158_Telefraud Detection.cpp └── A1159_Structure of a Binary Tree.cpp ├── README.md ├── image └── c++.jpg ├── 北大程序设计与算法专项课程 ├── .DS_Store ├── C++程序设计.md ├── 数据结构基础 │ ├── .DS_Store │ ├── 二叉树基础_实现堆结构.cpp │ ├── 二叉树基础_由中根序列和后根序列重建二叉树.cpp │ ├── 字符串_拼写检查.cpp │ ├── 字符串_英语数字转换器.cpp │ ├── 栈与队列_ 出栈序列统计.cpp │ ├── 栈与队列_密码翻译.cpp │ ├── 栈与队列_等价表达式.cpp │ ├── 线性表_多项式加法.cpp │ ├── 线性表_大整数乘法.cpp │ └── 线性表_约瑟夫问题.cpp └── 算法基础 │ ├── .DS_Store │ ├── 二分贪心_Aggressive cows.cpp │ ├── 二分贪心_Gone Fishing.cpp │ ├── 二分贪心_Yogurt factory.cpp │ ├── 动态规划_UNIMODAL PALINDROMIC DECOMPOSITIONS.cpp │ ├── 动态规划_charm_bracelet.cpp │ ├── 动态规划_滑雪.cpp │ ├── 动态规划_集合加法.cpp │ ├── 广搜_Flip Game.cpp │ ├── 广搜_迷宫问题.cpp │ ├── 期末考试_Minecraft.cpp │ ├── 期末考试_垃圾炸弹.cpp │ ├── 期末考试_复杂的整数划分问题.cpp │ ├── 期末考试_最大公约数.cpp │ ├── 期末考试_潘多拉星球的悬浮公寓.cpp │ ├── 期末考试_献给阿尔吉侬的花束.cpp │ ├── 期末考试_简单的整数划分问题.cpp │ ├── 枚举_拨钟问题.cpp │ ├── 枚举_画家问题.cpp │ ├── 深搜_ Shredding Company.cpp │ ├── 深搜_A Knight's Journey.cpp │ ├── 深搜_棋盘问题.cpp │ ├── 递归_完美覆盖.cpp │ └── 递归_文件结构图.cpp ├── 浙大数据结构 ├── 第三周_List_leaves.cpp ├── 第三周_树的同构.cpp ├── 第二周_线性结构_一元多项式的乘法与加法运算.cpp ├── 第四周_Root of AVL Tree.cpp └── 第四周_是否同一棵二叉搜索树.cpp ├── 真题模拟 ├── .DS_Store ├── 1031 Hello World for U.cpp ├── 1032 Sharing.cpp ├── 1033 To Fill or Not to Fill.cpp ├── 1034 Head of a Gang.cpp ├── 1035 Password.cpp ├── 1036 Boys vs Girls.cpp ├── 1037 Magic Coupon.cpp ├── 1038 Recover the Smallest Number.cpp ├── 1136 A Delayed Palindrome .cpp ├── 1152 Google Recruitment.cpp ├── A1118_Birds in Forest.cpp ├── A1137_Final Grading.cpp ├── A1138_Postorder Traversal.cpp ├── A1139_First Contact.cpp ├── A1140_Look-and-say Sequence.cpp ├── A1141_PAT Ranking of Institutions.cpp ├── A1142_Maximal Clique.cpp ├── A1143_Lowest Common Ancestor.cpp ├── A1144_The Missing Number.cpp ├── A1145_Hashing - Average Search Time .cpp ├── A1146_Topological Order.cpp ├── A1147_Heaps .cpp ├── A1148_Werewolf - Simple Version.cpp ├── A1149_Dangerous Goods Packaging .cpp ├── A1150_Travelling Salesman Problem.cpp └── A1151_LCA in a Binary Tree.cpp ├── 算法笔记 ├── .DS_Store ├── A1001_A+B Format.cpp ├── A1004_Counting Leaves .cpp ├── A1005_Spell It Right .cpp ├── A1007_Maximum Subsequence Sum.cpp ├── A1008_Elevator.cpp ├── A1010_Radix.cpp ├── A1012_The Best Rank.cpp ├── A1012_The Best Rank_ugly_version.cpp ├── A1013_Battle Over Cities.cpp ├── A1015_Reversible Primes.cpp ├── A1016_Phone Bills.cpp ├── A1017_Queueing at Bank.cpp ├── A1019_General Palindromic Number.cpp ├── A1020_Tree Traversals.cpp ├── A1021_Deepest Root .cpp ├── A1022_Digital Library.cpp ├── A1023_Have Fun with Numbers.cpp ├── A1024_Palindromic Number.cpp ├── A1025_PAT Ranking.cpp ├── A1027_Colors in Mars.cpp ├── A1028_List Sorting.cpp ├── A1029_Median.cpp ├── A1030_Travel Plan.cpp ├── A1031_Hello World for U.cpp ├── A1032_Sharing.cpp ├── A1033_To Fill or Not to Fill.cpp ├── A1034_Head of a Gang.cpp ├── A1035_Password.cpp ├── A1037_Magic Coupon.cpp ├── A1038 Recover the Smallest Number.cpp ├── A1039_Course List for Student.cpp ├── A1040_Longest Symmetric String.cpp ├── A1041_Be Unique.cpp ├── A1043_Is It a Binary Search Tree.cpp ├── A1044_Shopping in Mars .cpp ├── A1044_Shopping in Mars.cpp ├── A1045_Favorite Color Stripe.cpp ├── A1047_Student List for Course.cpp ├── A1048_Find Coins.cpp ├── A1049_Counting Ones.cpp ├── A1050_String Subtraction.cpp ├── A1051_Pop Sequence.cpp ├── A1052_Linked List Sorting.cpp ├── A1053_Path of Equal Weight.cpp ├── A1054_The Dominant Color .cpp ├── A1055_The World's Richest.cpp ├── A1056_Mice and Rice.cpp ├── A1057_Stack.cpp ├── A1058_A+B in Hogwarts.cpp ├── A1059_Prime Factors.cpp ├── A1060_Are They Equal .cpp ├── A1061_Dating.cpp ├── A1062_Talent and Virtu.cpp ├── A1063_Set Similarity.cpp ├── A1064_Complete Binary Search Tree.cpp ├── A1066_Root of AVL Tree.cpp ├── A1067 Sort with Swap(0, i).cpp ├── A1069_The Black Hole of Numbers.cpp ├── A1070_Mooncake.cpp ├── A1071_Speech Patterns.cpp ├── A1073_Scientific Notation.cpp ├── A1074_Reversing Linked List .cpp ├── A1075_PAT Judge.cpp ├── A1076_Forwards on Weibo.cpp ├── A1077_Kuchiguse.cpp ├── A1078_Hashing.cpp ├── A1079_Total Sales of Supply Chain.cpp ├── A1080_Graduate Admission.cpp ├── A1081_Rational Sum.cpp ├── A1082_Read Number in Chinese.cpp ├── A1083_List Grades.cpp ├── A1084_Broken Keyboard.cpp ├── A1085 Perfect Sequenc_upper_bound().cpp ├── A1085 Perfect Sequence_BinarySearch.cpp ├── A1085_Perfect Sequence_two_pointers.cpp ├── A1086_Tree Traversals Again.cpp ├── A1088_Rational Arithmetic.cpp ├── A1089_Insert or Merge.cpp ├── A1090_Highest Price in Supply Chain.cpp ├── A1091_Acute Stroke.cpp ├── A1092_To Buy or Not to Buy.cpp ├── A1093_Count PAT's.cpp ├── A1094_The Largest Generation.cpp ├── A1095_Cars on Campus.cpp ├── A1096_Consecutive Factors.cpp ├── A1097_Deduplication on a Linked List.cpp ├── A1098_Insertion or Heap Sort .cpp ├── A1099_Build A Binary Search Tree.cpp ├── A1100_Mars Numbers.cpp ├── A1101_Quick Sort .cpp ├── A1102_Invert a Binary Tree.cpp ├── A1103_Integer Factorization.cpp ├── A1104_Sum of Number Segments.cpp ├── A1105_Spiral Matrix.cpp ├── A1106_Lowest Price in Supply Chain.cpp ├── A1107_Social Clusters.cpp ├── B1027_打印沙漏.cpp ├── B1037_在霍格沃茨找零钱.cpp ├── B1038_统计同成绩学生.cpp ├── B1042_字符统计.cpp ├── B1043_输出PATest.cpp ├── B1047_编程团体赛.cpp ├── B1048_数字加密.cpp ├── BFS解决矩阵块问题.cpp ├── C++字符串全排列.cpp ├── C++数字按升序全排列.cpp ├── DFS解决背包问题.cpp ├── N皇后问题_回溯法.cpp ├── N皇后问题_高效暴力法.cpp ├── 区间贪心.cpp └── 好朋友_并查集例题.cpp └── 读书笔记 └── .DS_Store /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/.DS_Store -------------------------------------------------------------------------------- /2018.12.9 PAT 甲级冬考小结.md: -------------------------------------------------------------------------------- 1 | # 2018.12.9 PAT 甲级冬考小结 2 | 3 | 总的来说并不满意。题目都会。但是没有拿到该拿的全部分数。 4 | 5 | * 第一题,在长度为L的数字字符串中寻找第一个长度为k的素数子串。 6 | 7 | 题目难度不大,但是背景还算新颖?不同于以往一眼看破的水题,花了几分钟提取本质,一个2分测试点没过。为了节省时间直接往后,打算回头解决。此时过去了21分钟左右。 8 | 9 | * 第二题,老套的模拟查询题。这种题型之前做的很熟练也自认为掌握了,所以自信满满地开始读题。 10 | 11 | 前两种查询方式很老套,但是第三种根据日期输出考点编号及考点人数让我混乱了。我对这种题目的处理方式一般是在接收数据时就存储到数据结构里。但是考点的状态在数据接收完之前是不固定的,意味着要后期去提取。于是想到遍历第二个map数组即<考点id, 考点数据>。但是又不对,因为第三种查询方式需要日期作为键,而一个考点又可以被分为多个日期。仿佛要建立map<日期,map<某日期的考点, 数据> >这样的数据结构?当时心想是不是自己想的太复杂了。 12 | 13 | **接下来犯了一个大失误**:我决定忽略第三种查询方式,先实现前两种。前面思考的太混乱,导致写的慢,大概花了四十来分钟。再回头思考第三种,还是没有思路,此时已经过去了一个小时。看着耗了这么多时间的“老套题”完全没有产出成果,心态有点崩(之前做这种题都是一遍AC)。 14 | 15 | 缓了缓,保存代码。打起精神先跳过,看下一道。 16 | 17 | (之前做这种题都会把IO说明和思路写在头注释里,百发百中,只要写了都是一遍AC,**这次没写也是大失误**! 18 | 19 | 为啥没写呢。。因为屏幕太辣眼睛里,不想多看一眼。。还因为当时是开着网页 然后开dev c++小窗在上面 对着题目写 但是!小窗太小了!写了注释的话即使要看也要往上拉很长,所以干脆不写了。。但是!!**你写在头注释里了不就不用回头看题了嘛!!** 以及最后半小时才意识到可以把dev c++的侧栏隐藏视野扩大了好多,之前写的超级憋屈难怪那么烦躁。。) 20 | 21 | * 第三题,常规的图题。处于同一条边上的顶点不能是同一个颜色,给定每个顶点颜色,判断是否合法。 22 | 23 | 第一遍读完潜意识就觉得这题简单。但被前一题影响到,思路花了十来分钟才成型,在代码实现过程中对混乱的地方做了修订。其实总结起来很简单,读取边时用邻接表存储顶点u的邻接端点,读入给定颜色序列的时候用map标记顶点和对应颜色。接下来只要遍历每个节点的邻接点,从map得到两个顶点的颜色,如果相等就是非法,同时用哈希表标记不同颜色个数即可。 24 | 25 | 这么简单的思路,当时真是被前一题冲昏了头脑,一度想弃考算了。还好咬咬牙坚持了下来,一个2分测试点没过。没时间管,看下一题。此时还剩一个小时。 26 | 27 | * 第四题,输出数组形态树的路径遍历,右路径先于左路径,并判断大小堆。 28 | 29 | 拿到也是有自信的。遍历嘛,dfs递归,右路径先于左路径,就把2\*roo+1放在2*root前面,判断大小堆更简单了,直接调用algorithm的is_heap()函数。 30 | 31 | 刷刷写完代码,诡异的事情出现了,样例输出404???很奇怪的输出,以为是第一题的编译结果干扰到这题了就在dev c++里叉掉了第一题的代码,重新编译。还是404的输出。其他样例输出也不对。懵逼。 32 | 33 | 对于遍历,不递归还真不会做了。。但是递归哪里写错了呢?调不出来。。对递归的使用还是不够熟练啊QAQ 之前都是看的多,但是自己写的很少。得加强训练。 34 | 35 | 至于函数,不知道是什么问题,先占坑。 36 | 37 | * 硬件上的问题。 38 | 39 | dev c++的配色方案着实辣眼睛,尤其是那个荧光色加亮光标整行,在白底上快要闪瞎我了,荧光色配黑底就看不清代码了,换高亮颜色嘛,深的看不清,浅的就是荧光色。。在敲括号的时候,鲜红色的括号配上荧光色。。。瞎了。。。得摸索一套配色方案出来,下次换上。。 40 | 41 | PAT题目样例输入不能复制( ・᷄ὢ・᷅ )?第二题的输入数据,手打会shi吧。。有什么办法呢~谁让你不能一遍AC~ 42 | 43 | 44 | 45 | ## 三月,再战!目标是满分💯!! 46 | 47 | -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/.DS_Store -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/DemoCode/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/DemoCode/.DS_Store -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/.DS_Store -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/AVLInsertCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/AVLInsertCode.png -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/AVLRotation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/AVLRotation.png -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/ChangeVal.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/ChangeVal.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/ContainerwithIt.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/ContainerwithIt.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/DeleteVal.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/DeleteVal.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/Dijkstra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/Dijkstra.png -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/LL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/LL.png -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/LR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/LR.png -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/ListIt.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/ListIt.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/ListMFuncs.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/ListMFuncs.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/NotChangeOrder.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/NotChangeOrder.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/OperateOrdered.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/OperateOrdered.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/RotationSum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/RotationSum.png -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/Sort.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/Sort.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/changeOrder.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/changeOrder.jpeg -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/iterator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/iterator.png -------------------------------------------------------------------------------- /C++11_STL_CheatSheet/STLimg/preOrderAndinOrder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/C++11_STL_CheatSheet/STLimg/preOrderAndinOrder.png -------------------------------------------------------------------------------- /PAT真题After算法笔记/1156-1159题目.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/PAT真题After算法笔记/1156-1159题目.docx -------------------------------------------------------------------------------- /PAT真题After算法笔记/A1156_Sexy Primes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | bool isPrime(int n) { 6 | if (n <= 1) return false; 7 | int sqr = int(sqrt(1.0 * n)); 8 | for (int i = 2; i <= sqr; ++i) { 9 | if (n % i == 0) return false; 10 | } 11 | return true; 12 | } 13 | 14 | int main() { 15 | int n; scanf("%d", &n); 16 | bool flag = true; 17 | if (isPrime(n)) { 18 | if (isPrime(n-6)) printf("Yes\n%d\n", n-6); 19 | else if (isPrime(n+6)) printf("Yes\n%d\n", n+6); 20 | else flag = false; 21 | } 22 | else flag = false; 23 | if (!flag) { 24 | printf("No\n"); 25 | while (!isPrime(n) || !( isPrime(n+6) || isPrime(n-6)) ) ++n; 26 | printf("%d\n", n); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /PAT真题After算法笔记/A1157_Anniversary.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | bool cmp(string a, string b) { 9 | return a.substr(6, 13) < b.substr(6, 13); 10 | } 11 | 12 | int main() { 13 | int n, m; string name; 14 | unordered_map mp; 15 | vector all, ans; 16 | cin >> n; 17 | for (int i = 0; i < n; ++i) { 18 | cin >> name; mp[name] = true; 19 | } 20 | cin >> m; 21 | for (int i = 0; i < m; ++i) { 22 | cin >> name; 23 | all.push_back(name); 24 | if (mp[name]) ans.push_back(name); 25 | } 26 | printf("%d\n", ans.size()); 27 | if (!ans.empty()) { 28 | sort(ans.begin(), ans.end(), cmp); 29 | printf("%s\n", ans[0].c_str()); 30 | } 31 | else { 32 | sort(all.begin(), all.end(), cmp); 33 | printf("%s\n", all[0].c_str()); 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 浙大PAT甲级备考 2 | 3 | 4 | ### 刷题 5 | - [ ] 甲级真题二刷(19年2月开始每天一套) 6 | - [X] 算法笔记(晴神宝典)实现一遍 7 | - [X] 算法笔记上机训练实战指南实现一遍 8 | 9 | 10 | ### 网课 11 | - [X] 浙大数据结构(*不是很合胃口 认真学到了AVL 后面走马观花扫了一遍*) 12 | - [ ] 北大程序设计与算法专项课程pku 13 | - [X] 计算导论与C语言基础 14 | - [X] C程序设计进阶 15 | - [X] C++程序设计 16 | - [X] 算法基础 17 | - [X] 数据结构 18 | - [ ] 高级数据结构与算法 19 | 20 | ### 读书笔记 21 | - [ ] 大话数据结构 22 | 23 | ### 费曼学习法 24 | 25 | 以教促学٩(˃̶͈̀௰˂̶͈́)و 26 | 27 | - [ ] 算法笔记教学视频 28 | - [ ] PAT甲级刷题教学 29 | 30 | 31 | 32 | ### 实用资源 33 | 34 | - [数据结构动画演示](https://visualgo.net/en) 35 | - [酷炫的排序动画](http://sorting.at/) 36 | - [神器:标准模版库STL](https://github.com/merelydust/PAT-Advanced-Level/tree/master/C%2B%2B11_STL_CheatSheet) 37 | 38 | 39 | 如果对你有所帮助(⁎⁍̴̛ᴗ⁍̴̛⁎)请Star+Follow~ 40 | 帮助你、帮助我 成为更加优秀的Programmer∠( ᐛ 」∠)_ 41 | -------------------------------------------------------------------------------- /image/c++.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/image/c++.jpg -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/北大程序设计与算法专项课程/.DS_Store -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/北大程序设计与算法专项课程/数据结构基础/.DS_Store -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/二叉树基础_实现堆结构.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | int t; scanf("%d", &t); 9 | while (t--) { 10 | int n; scanf("%d", &n); 11 | vector v; make_heap(v.begin(), v.end(), greater()); 12 | while (n--) { 13 | int u; scanf("%d", &u); 14 | if (u == 1) { 15 | int num; scanf("%d", &num); 16 | v.push_back(num); 17 | push_heap(v.begin(), v.end(), greater()); 18 | } 19 | else if (u== 2) { 20 | pop_heap(v.begin(), v.end(), greater()); 21 | printf("%d\n", v.back()); 22 | v.pop_back(); 23 | } 24 | } 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/二叉树基础_由中根序列和后根序列重建二叉树.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | const int maxn = 66000; 3 | int in[maxn], post[maxn]; 4 | 5 | struct node { 6 | int data; 7 | node* left; 8 | node* right; 9 | node() { 10 | left = right = NULL; 11 | } 12 | }; 13 | 14 | node* create(int postL, int postR, int inL, int inR) { 15 | if (postL > postR) return NULL; 16 | node* root = new node; 17 | root->data = post[postR]; 18 | int rootPos = inL; 19 | while (in[rootPos] != root->data) ++rootPos; 20 | int numLeft = rootPos - inL; 21 | root->left = create(postL, postL+numLeft-1, inL, rootPos-1); 22 | root->right = create(postL+numLeft, postR-1, rootPos+1, inR); 23 | return root; 24 | } 25 | 26 | void preTraversal(node* root) { 27 | if (root == NULL) return; 28 | printf("%d ", root->data); 29 | preTraversal(root->left); 30 | preTraversal(root->right); 31 | delete root; 32 | } 33 | 34 | int main() { 35 | int cnt = 0; 36 | while (scanf("%d", &in[cnt++])) { 37 | if (getchar() == '\n') break; 38 | } 39 | for (int i = 0; i < cnt; ++i) scanf("%d", &post[i]); 40 | node* root = create(0, cnt-1, 0, cnt-1); 41 | preTraversal(root); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/字符串_拼写检查.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | int main() 5 | { 6 | string a[10001]; 7 | int i=0; 8 | int j; 9 | while(cin>>a[i]) 10 | { 11 | if(a[i]=="#") 12 | break; 13 | i++; 14 | } 15 | string x; 16 | string b; 17 | while(cin>>x) 18 | { 19 | b=""; 20 | if(x=="#") 21 | break; 22 | for(j=0;j 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | string word[] = {"negative","zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety","hundred","thousand","million"}; 7 | int number[] = {-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,30,40,50,60,70,80,90,100,1000,1000000}; 8 | string str; 9 | int num,temp; 10 | vector res;//存放分割的字符 11 | vector::iterator ite; 12 | int pos; 13 | 14 | //分割输入的字符串 15 | void split(){ 16 | res.clear(); 17 | char *cstr,*p; 18 | cstr = new char[str.size()+1]; 19 | cstr = strcpy(cstr,str.c_str()); 20 | p = strtok(cstr," ");//空格作为分隔符 21 | while (p != NULL){ 22 | res.push_back(p); 23 | p = strtok(NULL," ");//第一次调用后再次调用要将字符串参数置空 24 | } 25 | } 26 | 27 | void Eng2Num(){ 28 | temp = 0; 29 | for (ite = res.begin();ite != res.end();ite++){ 30 | for (string::size_type i = 0;i < 32;i++){ 31 | if (*ite == word[i]){ 32 | pos = i; 33 | break; 34 | } 35 | } 36 | 37 | //若第一个字符为negative,则为负数 38 | if (pos == 0){ 39 | cout << "-"; 40 | }else if (pos == 29){//出现hundred的情况 41 | temp *= number[pos]; 42 | }else if (pos >= 30){//不会出现thousand和million一起的情况,放在一起讨论 43 | temp *= number[pos]; 44 | num += temp; 45 | temp = 0; 46 | }else{//小于100直接相加即可 47 | temp += number[pos]; 48 | } 49 | } 50 | num += temp; 51 | cout << num << endl; 52 | } 53 | 54 | int main() { 55 | while (getline(cin,str)){//字符串中有空格,选用getline()输入 56 | if (str.empty()) break; 57 | num = 0; 58 | split();//分割输入的字符串 59 | Eng2Num();//将英语转换为数字 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/栈与队列_ 出栈序列统计.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | stack s; int cnt = 0, n; 6 | void solve(int in, int out) { // in已经入栈 out等待入栈 7 | if (out == 0) { // 元素已经全部入栈 out=0 8 | ++cnt; return; 9 | } 10 | else if (in == 0) solve(in+1, out-1); // 没有元素入栈 in = 0 11 | else if (out) { // 既能入栈又能出栈 12 | solve(in+1, out-1); // 继续入栈的分支 13 | solve(in-1, out); // 出栈的分支 出栈的元素被输出了而不是回到待定区 所以out不变 14 | } 15 | } 16 | 17 | int main() { 18 | scanf("%d", &n); 19 | solve(0, n); 20 | printf("%d\n", cnt); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/栈与队列_密码翻译.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | int n; scanf("%d", &n); 6 | char c; scanf("%c", &c); // 数字后面也有换行符 7 | while (n--) { 8 | while (scanf("%c", &c) != EOF && c != '\n') { 9 | if (isalpha(c)) { 10 | ++c; 11 | if (c == 91) c = 65; 12 | else if (c == 123) c = 97; 13 | } 14 | printf("%c", c); 15 | } 16 | printf("\n"); 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/线性表_多项式加法.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int n; scanf("%d", &n); 8 | while (n--) { 9 | int co, ex; 10 | map > mp; 11 | while (scanf("%d %d", &co, &ex) != EOF) { 12 | if (ex < 0) break; 13 | mp[ex] += co; 14 | } 15 | while (scanf("%d %d", &co, &ex) != EOF) { 16 | if (ex < 0) break; 17 | mp[ex] += co; 18 | } 19 | map::iterator it = mp.begin(); 20 | for (; it != mp.end(); ++it) { 21 | if (it != mp.begin()) printf(" "); 22 | if (it->second) printf("[ %d %d ]", it->second, it->first); 23 | } 24 | printf("\n"); 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/数据结构基础/线性表_大整数乘法.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | const int maxn = 210; 5 | 6 | int main() 7 | { 8 | string str1, str2; cin >> str1 >> str2; 9 | int len1 = str1.length(), len2 = str2.length(); 10 | int i, j; 11 | int a[maxn], b[maxn], ans[2*maxn]={0}; 12 | for(i=len1-1, j=0; i>=0; i--) a[j++]=str1[i]-'0'; 13 | for(i=len2-1, j=0; i>=0; i--) b[j++]=str2[i]-'0'; 14 | for( i=0; i=10 )//大于9进位 20 | { 21 | ans[i+j+1]+=ans[i+j]/10; 22 | ans[i+j]%=10; 23 | } 24 | } 25 | } 26 | //长度为len1和len的两数相乘,最多有len1+len2位,最少有len1+len2-1位 27 | i=len1+len2-1; 28 | if( ans[i]==0 )//检验第len1+len2位是否为0,若为0, 则不输出 29 | i--; 30 | for(i; i>=0; i--)//输出 31 | cout< 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | int n, m; scanf("%d %d", &n, &m); 7 | m = m % n; 8 | list lst; 9 | for (int i = 1; i <= n; ++i) lst.push_back(i); 10 | list::iterator it = lst.begin(); 11 | while (lst.size() > 1) { 12 | for (int i = 0; i < m; ++i) { 13 | if (++it == lst.end()) it = lst.begin(); 14 | } 15 | it = lst.erase(it); 16 | if (it == lst.end()) it = lst.begin(); 17 | } 18 | printf("%d\n", *it); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/北大程序设计与算法专项课程/算法基础/.DS_Store -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/二分贪心_Aggressive cows.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 牛跟牛之间有安全距离 即最小距离 3 | 要求这个安全距离的最大值 4 | ***/ 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | const int maxn = 100010; 10 | int n, c; 11 | int stall[maxn] = {0}; 12 | 13 | bool check(int tmpdis) { // 验证按照tmpdis的间隔 能否安排全部C头牛 14 | int nCow = 0; // 已安置的牛数量 15 | int nowRight = stall[0]; // 把第一头牛放在第一个区间 16 | for (int i = 1; i <= n; ++i) { 17 | if (nowRight <= stall[i]) { // 如果已安排区间的右端点在下一个栏点左边 则该右端点和该栏点构成一个新区间 可以安排进一只牛 18 | ++nCow; nowRight = stall[i] + tmpdis; 19 | } 20 | } 21 | if (nCow >= c) return true; // 如果可以安排的牛数>=给定的牛数 22 | else return false; 23 | } 24 | 25 | int main() { 26 | scanf("%d %d", &n, &c); 27 | for (int i = 1; i <= n; ++i) scanf("%d", &stall[i]); 28 | sort(&stall[1], (&stall[1])+n); 29 | int left = 1, right = (stall[n]-stall[0]) / (c-1), ans = 0; 30 | int mid = 0; // 如果只有一个栏点 right=0 31 | while (left <= right) { 32 | mid = (left + right) / 2; 33 | if (check(mid)) { 34 | ans = mid; // 保存此时的mid值 因为之后进行到退出循环操作时check(mid)可能是无效的 35 | left = mid + 1; 36 | } 37 | else right = mid-1; // 牛安排不完 tmpdis要拉小 右端点左移 38 | } 39 | printf("%d\n", ans); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/二分贪心_Gone Fishing.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | h小时 n个湖 3 | 从湖1开始 任意湖结束 4 | 湖之间的移动时间=5*ti分钟 5 | 每个湖起始5分钟期望抓到的鱼数量fi 每过去五分钟期望抓鱼会下降di 6 | 期望抓鱼数<=di的时间段 不会抓到鱼 7 | 最大化抓到的鱼 8 | 9 | 输出 多个测试用例 10 | n 11 | h 12 | a line of n integers specifying fi (1 <= i <=n) 13 | a line of n integers di (1 <=i <=n) 14 | a line of n - 1 integers ti 15 | 遇到n=0终止测试 16 | 17 | 18 | 输出在每个湖停留时间 用逗号分隔 19 | Number of fish expected: maxFish 20 | 21 | 枚举所有湖 以湖i为钓鱼终点 *因为不走回头路 回头是浪费时间 22 | 思路 总是选择 每单位时间抓到的鱼最多的湖 23 | 24 | ***/ 25 | #include 26 | #include 27 | using namespace std; 28 | const int maxn = 30; 29 | 30 | int n, h; 31 | int t[maxn], f[maxn], d[maxn], cf[maxn]; // cf 湖i当前五分钟能钓的鱼 32 | int ans, sum[maxn]; 33 | 34 | void get_max(int k, int& ans, int sum[]) { // 以湖k为终点 35 | int maxFish = -1, id = -1; 36 | for (int i = 1; i <= k; ++i) { 37 | if (cf[i] > maxFish) { 38 | maxFish = cf[i]; id = i; 39 | } 40 | } 41 | ans += cf[id]; ++sum[id]; cf[id] -= d[id]; 42 | if (cf[id] < 0) cf[id] = 0; // 题目挂羊头卖狗肉 43 | } 44 | 45 | void solve() { 46 | for (int i = 1; i <= n; ++i) { // 枚举终点湖 47 | int fish_time = h; // 用于钓鱼的时间 48 | for (int j = 1; j < i; ++j) fish_time -= t[j]; // 总时间减掉走路时间 49 | int tmp_ans = 0, tmp_sum[maxn]={0}; 50 | memcpy(cf, f, sizeof(f)); 51 | for (int j = 0; j < fish_time; ++j) get_max(i, tmp_ans, tmp_sum); 52 | if (tmp_ans > ans) { 53 | ans = tmp_ans; memcpy(sum, tmp_sum, sizeof(sum)); 54 | } 55 | } 56 | for (int i = 1; i <= n; ++i) { 57 | if (i > 1) printf(", "); 58 | printf("%d", sum[i]*5); 59 | } 60 | printf("\nNumber of fish expected: %d\n\n",ans); // Insert a blank line between cases. 61 | } 62 | 63 | int main() { 64 | while (scanf("%d", &n) && n) { 65 | scanf("%d", &h); 66 | h *= 12; 67 | memset(sum, 0, sizeof(sum)); ans = 0; sum[1] = h; 68 | sum[1] = h; 69 | for(int i=1;i<=n;i++) scanf("%d",&f[i]); 70 | for(int i=1;i<=n;i++) scanf("%d",&d[i]); 71 | for(int i=1;i<=n-1;i++) scanf("%d",&t[i]); 72 | solve(); 73 | } 74 | return 0; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/二分贪心_Yogurt factory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | const long long INF = 0x3f3f3f3f; 7 | int n, s, c, y, m = INF; // m-某周单位生产的最小代价 8 | long long ans = 0; 9 | scanf("%d %d", &n, &s); 10 | for (int i = 0; i < n; ++i) { 11 | scanf("%d %d", &c, &y); 12 | m = min(c, m+s); // 本周单位最小代价 直接生产c/全部用上周的库存(上周生产成本m+存储成本s) 13 | ans += (long long)m*y; 14 | } 15 | printf("%lld\n", ans); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/动态规划_UNIMODAL PALINDROMIC DECOMPOSITIONS.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | unsigned int dp[250][250]; 7 | 8 | class Solution { 9 | public: 10 | unsigned int fun(int n) { 11 | //初始化数据, 边界条件 12 | for(int num=0; num<250; num++) { 13 | for (int k=0; k<250; k++) { 14 | if (num==0) { 15 | dp[num][k] = 1; 16 | } 17 | else if (k>num){ 18 | dp[num][k] = 0; 19 | } 20 | else { 21 | dp[num][k] = 1; 22 | } 23 | } 24 | } 25 | //动态规划 26 | for (int num=2; num<=n; num++) 27 | { 28 | for (int k=num/2; k>=1; k--) 29 | { 30 | dp[num][k] = dp[num-2*k][k] + dp[num][k+1]; 31 | } 32 | } 33 | return dp[n][1]; 34 | } 35 | }; 36 | 37 | int main() { 38 | Solution sol; 39 | int n; 40 | cin >> n; 41 | while(n != 0) { 42 | cout << n << ' ' << sol.fun(n) << endl; 43 | cin >> n; 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/动态规划_charm_bracelet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main(){ 6 | int N, M; 7 | cin >> N >> M; 8 | int wi, di; 9 | vector last(M+1, 0); 10 | vector next(M+1, 0); 11 | for (int i=0; i> wi >> di; 14 | copy(next.begin(), next.end(), last.begin()); 15 | for(int j=wi; j<=M; j++) { 16 | next[j] = max(last[j], last[j-wi]+di); 17 | } 18 | } 19 | cout << next[M] << endl; 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/动态规划_滑雪.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 110; 6 | int row, col, maxL = -1; 7 | int arr[maxn][maxn] = {0}; 8 | int dp[maxn][maxn] = {0}; 9 | int X[4] = {0, 0, 1, -1}; 10 | int Y[4] = {1, -1, 0, 0}; 11 | 12 | int cal(int x, int y) { 13 | if (dp[x][y]) return dp[x][y]; 14 | int preL = 0; // 该点向四周能滑的最长长度 15 | for (int i = 0; i < 4; ++i) { 16 | int newX = x + X[i], newY = y + Y[i]; 17 | if (newX < 0 || newX >= row || newY < 0 || newY >= col) continue; 18 | if (arr[newX][newY] < arr[x][y]) preL = max(preL, cal(newX, newY)); 19 | } 20 | dp[x][y] = preL + 1; // 该点能滑的最长长度=四周能滑的最长长度+1 21 | return dp[x][y]; 22 | } 23 | 24 | int main() { 25 | scanf("%d %d", &row, &col); 26 | for (int i = 0; i < row; ++i) { 27 | for (int j = 0; j < col; ++j) scanf("%d", &arr[i][j]); 28 | } 29 | for (int i = 0; i < row; ++i) { 30 | for (int j = 0; j < col; ++j) maxL = max(cal(i, j), maxL); 31 | } 32 | printf("%d\n", maxL); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/动态规划_集合加法.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 思路:数组a里有个num1 数组2里有个num2 num1+num2=sum 那么这种组合的个数就是a里num1的个数*b里num2的个数 3 | 数组.at[value] Returns the element at position n in the array. 4 | ***/ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int fun(const vector& a, const vector& b, const int sum) { 11 | int res=0; 12 | for (int i=0; i0) { 14 | if (sum >= i) { 15 | res += a.at(i) * b.at(sum-i); 16 | } 17 | } 18 | } 19 | return res; 20 | } 21 | 22 | int main() { 23 | int n; 24 | cin >> n; 25 | int sum=0; 26 | int a=0, b=0; 27 | int temp_a=0, temp_b=0; 28 | while(n--) { 29 | vector vector_a(10001, 0), vector_b(10001, 0); 30 | cin >> sum; 31 | cin >> a; 32 | for(int i=0; i> temp_a; 34 | vector_a.at(temp_a)++; 35 | } 36 | cin >> b; 37 | for(int i=0; i> temp_b; 39 | vector_b.at(temp_b)++; 40 | } 41 | cout << fun(vector_a, vector_b, sum) << endl; 42 | } 43 | return 1; 44 | } 45 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/广搜_Flip Game.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int chess[4][4]; 5 | int mincnt = 17; // 棋子翻转偶数次=翻转0次 翻转奇数次=翻转1次 所以最多翻16次 初始化为非法值 6 | 7 | void build() { 8 | char c; 9 | for (int i = 0; i < 4; ++i) { 10 | for (int j = 0; j <4; ++j) { 11 | cin >> c; 12 | if (c == 'w') chess[i][j] = 0; 13 | else chess[i][j] = 1; 14 | } 15 | } 16 | } 17 | 18 | void turn(int x, int y) { // 翻转第x行y列的棋子 19 | if (x >= 0 && x < 4 && y >= 0 && y < 4) chess[x][y] = !chess[x][y]; 20 | } 21 | 22 | void flip(int now) { // 模拟翻转第now个棋子 23 | int i = now / 4; // 行号 24 | int j = now % 4; // 列号 25 | turn(i,j); 26 | turn(i+1,j); 27 | turn(i,j+1); 28 | turn(i-1,j); 29 | turn(i,j-1); 30 | } 31 | 32 | bool complete() { 33 | int cnt = 0; 34 | for (int i = 0; i < 4; ++i) { 35 | for (int j = 0; j < 4; ++j) cnt += chess[i][j]; 36 | } 37 | if (cnt % 16 == 0) return true; // 如果cnt为16全黑或为0全白 38 | else return false; 39 | } 40 | 41 | void dfs(int now, int flipCnt) { // now当前棋子 flipCnt翻转的棋子个数 42 | if (complete()) { 43 | if (mincnt > flipCnt) mincnt = flipCnt; // 更新mincnt 44 | return; 45 | } 46 | if (now >= 16) return; // 棋子全部翻过一遍 47 | dfs(now+1, flipCnt); // 不翻转now的分支 48 | flip(now); // 翻转now的分支 49 | dfs(now+1, flipCnt+1); 50 | flip(now); // 结束翻转now的分支 还原状态 51 | } 52 | 53 | int main() { 54 | build(); 55 | dfs(0, 0); 56 | if (mincnt == 17) cout << "Impossible" << endl; 57 | else cout << mincnt << endl; 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/广搜_迷宫问题.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct node { 7 | int x, y, data; 8 | node* pre; 9 | node() { 10 | pre = NULL; 11 | } 12 | }matrix[5][5]; 13 | 14 | int inq[5][5] = {0}; 15 | int ans = 50; vector path; 16 | int X[4] = {1, -1, 0, 0}; 17 | int Y[4] = {0, 0, 1, -1}; 18 | 19 | bool judge(int x, int y) { 20 | if (x < 0 || x > 4 || y < 0 || y > 4 || matrix[x][y].data || inq[x][y]) return false; 21 | return true; 22 | } 23 | 24 | void bfs() { 25 | queue Q; 26 | Q.push(matrix[0][0]); 27 | while (!Q.empty()) { 28 | node fro = Q.front(); Q.pop(); 29 | inq[0][0] = 1; 30 | if (fro.x == 4 && fro.y == 4) return; 31 | for (int i = 0; i < 4; ++i) { 32 | int newX = fro.x + X[i], newY = fro.y+Y[i]; 33 | if (judge(newX, newY)) { 34 | node Node; Node.x = newX; Node.y = newY; 35 | matrix[newX][newY].pre = &(matrix[fro.x][fro.y]); // 队列传入的是副本~所以手动操作matrix 36 | Q.push(Node); inq[Node.x][Node.y] = 1; 37 | } 38 | } 39 | } 40 | } 41 | 42 | int main() { 43 | for (int i = 0; i < 5; ++i) { 44 | for (int j = 0; j < 5; ++j) { 45 | scanf("%d", &matrix[i][j].data); 46 | matrix[i][j].x = i; matrix[i][j].y = j; 47 | } 48 | } 49 | bfs(); 50 | node* ptr = &(matrix[4][4]); 51 | while (ptr != NULL) { 52 | path.push_back(*(ptr)); 53 | ptr = ptr->pre; 54 | } 55 | for (int i = path.size()-1; i >= 0; --i) { 56 | printf("(%d, %d)\n", path[i].x, path[i].y); 57 | } 58 | return 0; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/期末考试_Minecraft.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | int t,n,x,ans; 6 | inline int calc(int a,int b,int c){ 7 | return a*b*2+a*c*2+b*c*2; 8 | } 9 | int main(){ 10 | scanf("%d",&t); 11 | while(t--){ 12 | scanf("%d",&n); 13 | x = n; ans = INT_MAX; 14 | for(int i = 1;i <= n; ++i){ 15 | if(x%i == 0){ 16 | x/=i; 17 | for(int j=1; j <= x; j++){ 18 | if(x%j == 0){ 19 | x/=j; 20 | ans = min(ans, calc(i,j,x)); 21 | x *= j; 22 | } 23 | } 24 | x*=i; 25 | } 26 | } 27 | printf("%d\n",ans); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/期末考试_垃圾炸弹.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 1025; 7 | struct node { 8 | int x, y, data; 9 | }nodes[30]; 10 | 11 | int mp[maxn][maxn] = {0}; // 枚举地图上每个点 找到处理垃圾最多的 12 | 13 | int main() { 14 | int d, n; scanf("%d %d", &d, &n); 15 | for (int i = 0; i < n; ++i) scanf("%d %d %d", &nodes[i].x, &nodes[i].y, &nodes[i].data); 16 | int ans = 0, nPlace = 0; // 最多处理垃圾 能达到ans的投放点数量 17 | for (int i = 0; i < n; ++i) { 18 | for (int row = nodes[i].x-d; row <= nodes[i].x + d; ++row) { 19 | if (row < 0 || row >= maxn) continue; 20 | for (int col = nodes[i].y-d; col <= nodes[i].y + d; ++col) { 21 | if (col < 0 || col >= maxn) continue; 22 | mp[row][col] += nodes[i].data; // 在该点投放能处理的垃圾数量加上d范围内垃圾点的垃圾量 23 | if (ans < mp[row][col]) { // 更新最多处理垃圾 24 | ans = mp[row][col]; nPlace = 1; 25 | } 26 | else if (ans == mp[row][col]) ++nPlace; 27 | } 28 | } 29 | } 30 | printf("%d %d\n", nPlace, ans); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/期末考试_复杂的整数划分问题.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | int n, k; 8 | while( cin >> n >> k ) 9 | { 10 | int num[n+1][n+1]; // 表示把n分成k个数的dp数组; 11 | int num1[n+1][n+1]; // 表示把n分成不相等正整数的dp数组; 12 | int g[55][55], f[55][55]; // g数组为偶数dp数组, f数组为奇数dp数组; 13 | int i, j; 14 | // 初始化; 15 | for( i=0; i<=n; i++ ) 16 | { 17 | for( j=0; j<=n; j++ ) 18 | { 19 | num[i][j] = num1[i][j] = f[i][j] = g[i][j] = 0; 20 | } 21 | } 22 | // 这就是上面说的其中两种。 23 | for( i=1; i<=n; i++) 24 | { 25 | for( j=1; j<=n; j++) 26 | { 27 | if( i < j ) 28 | { 29 | num[i][j] = 0; 30 | num1[i][j] = num1[i][j-1]; 31 | } 32 | if( i == j ) 33 | { 34 | num[i][j] = 1; 35 | num1[i][j] = 1 + num1[i][j-1]; 36 | } 37 | if( i > j ) 38 | { 39 | num[i][j] = num[i-1][j-1] + num[i-j][j]; 40 | num1[i][j] = num1[i-j][j-1] + num1[i][j-1]; 41 | } 42 | } 43 | } 44 | // 这里是最晕的,只要记住就好了,搞懂也没多大意义; 45 | f[0][0]=1; g[0][0]=1; 46 | for( i=1; i<=n; i++ ) 47 | { 48 | for( j=1; j<=i; j++) 49 | { 50 | g[i][j] = f[i-j][j]; 51 | f[i][j] = f[i-1][j-1] + g[i-j][j]; 52 | 53 | } 54 | } 55 | 56 | cout << num[n][k] < 2 | using namespace std; 3 | 4 | int gcd(int a, int b) { 5 | return !b ? a : gcd(b, a % b); 6 | } 7 | 8 | int main() { 9 | int a, b; 10 | while (scanf("%d %d", &a, &b) != EOF) printf("%d\n", gcd(a, b)); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/期末考试_献给阿尔吉侬的花束.cpp: -------------------------------------------------------------------------------- 1 | // scanf读取char与换行符不得不说的坑爹故事 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | const int maxn = 210; 8 | 9 | struct node { 10 | int x, y, step; 11 | char data; 12 | }mp[maxn][maxn]; 13 | node S, E; 14 | 15 | int inq[maxn][maxn]; 16 | int X[4] = {0, 0, 1, -1}; 17 | int Y[4] = {1, -1, 0, 0}; 18 | 19 | int row, col; 20 | bool judge(int x, int y) { 21 | if (x < 0 || x >= row || y < 0 || y >= col || mp[x][y].data == '#' || inq[x][y]) return false; 22 | return true; 23 | } 24 | 25 | int solve() { 26 | queue Q; 27 | Q.push(S); inq[S.x][S.y] = 1; 28 | while (!Q.empty()) { 29 | node fro = Q.front(); Q.pop(); 30 | if (fro.x == E.x && fro.y == E.y) return fro.step; 31 | for (int i = 0; i < 4; ++i) { 32 | int newX = fro.x + X[i], newY = fro.y + Y[i]; 33 | if (judge(newX, newY)) { 34 | mp[newX][newY].step = fro.step + 1; 35 | Q.push(mp[newX][newY]); inq[newX][newY] = 1; 36 | } 37 | } 38 | } 39 | return -1; // 无法到达 40 | } 41 | 42 | int main() { 43 | int t; cin >> t; 44 | while (t--) { 45 | cin >> row >> col; 46 | for (int i = 0; i < row; ++i) { 47 | for (int j = 0; j < col; ++j) { 48 | cin >> mp[i][j].data; mp[i][j].x = i; mp[i][j].y = j; 49 | if (mp[i][j].data == 'S') S = mp[i][j]; 50 | else if (mp[i][j].data == 'E') E = mp[i][j]; 51 | } 52 | } 53 | memset(inq, 0, sizeof(inq)); mp[S.x][S.y].step = 0; 54 | int ans = solve(); 55 | if (ans != -1) printf("%d\n", ans); 56 | else printf("oop!\n"); 57 | } 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/期末考试_简单的整数划分问题.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | #define N 55 5 | int f[N][N],n,ans; 6 | int main(){ 7 | while(scanf("%d",&n)!=EOF){ 8 | f[0][0]=1; 9 | for(int i=1;i<=n;i++){ 10 | for(int j=1;j<=i;j++){ 11 | f[i][j]=f[i-1][j-1]+f[i-j][j]; 12 | } 13 | } 14 | ans=0; 15 | for(int i=1;i<=n;i++) ans+=f[n][i]; 16 | printf("%d\n",ans); 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/枚举_拨钟问题.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int z[10],i[10],sum; 3 | int main() 4 | { 5 | //只做前三重循环, 后六种根据前面推出 6 | // 因为除了1,2,3种操作,只有第四种能影响到A,只有第五种能影响到B 7 | // ...只有第六种能影响到I 8 | for(int j=1;j<=9;j++)scanf("%d",&z[j]); 9 | for(i[1]=0;i[1]<4;i[1]++) 10 | for(i[2]=0;i[2]<4;i[2]++) 11 | for(i[3]=0;i[3]<4;i[3]++) 12 | { 13 | i[4]=(4-(z[1]+i[1]+i[2])%4)%4; 14 | i[5]=(4-(z[2]+i[1]+i[2]+i[3])%4)%4; 15 | i[6]=(4-(z[3]+i[2]+i[3])%4)%4; 16 | i[7]=(4-(z[4]+i[1]+i[4]+i[5])%4)%4; 17 | i[9]=(4-(z[6]+i[3]+i[5]+i[6])%4)%4; 18 | i[8]=(4-(z[8]+i[5]+i[7]+i[9])%4)%4; 19 | sum=0; 20 | sum+=(z[1]+i[1]+i[2]+i[4])%4; 21 | sum+=(z[2]+i[1]+i[2]+i[3]+i[5])%4; 22 | sum+=(z[3]+i[2]+i[3]+i[6])%4; 23 | sum+=(z[4]+i[1]+i[4]+i[5]+i[7])%4; 24 | sum+=(z[5]+i[1]+i[3]+i[5]+i[7]+i[9])%4; 25 | sum+=(z[6]+i[3]+i[5]+i[6]+i[9])%4; 26 | sum+=(z[7]+i[4]+i[7]+i[8])%4; 27 | sum+=(z[8]+i[5]+i[7]+i[8]+i[9])%4; 28 | sum+=(z[9]+i[6]+i[8]+i[9])%4; 29 | if(sum==0) 30 | { 31 | for(int j=1;j<=9;j++) 32 | while(i[j]--) { 33 | printf("%d ",j); 34 | } 35 | return 0; 36 | } 37 | } 38 | return -1; 39 | } 40 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/深搜_ Shredding Company.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int num[7],tmp[7],len,mm,t,f;//num-分割方式 tmp-临时分割 len-分割组数 mm-最大分割和 f-判多解(rejected) 9 | 10 | int getlen(int x)//求x位数对应的10^n 用以dfs时取余(分割) 11 | { 12 | int cnt = 1; 13 | while(x) 14 | { 15 | x /= 10; 16 | cnt *= 10; 17 | } 18 | return cnt/10; 19 | } 20 | 21 | void dfs(int rest,int sum,int site,int l,int p)//p 0无前导零 1有前导 22 | { 23 | if(sum + rest <= t && sum + rest >= mm) 24 | { 25 | if(sum + rest == mm || p == 1)//满足条件时多解或某组有前导零 26 | { 27 | f = 1; 28 | mm = sum + rest; 29 | return; 30 | } 31 | f = 0; 32 | mm = sum + rest; 33 | memcpy(num,tmp,sizeof(tmp)); 34 | num[site++] = rest; 35 | len = site; 36 | return; 37 | } 38 | 39 | if(sum + rest < t && sum + rest < mm) return;//当前已小 后继更小 40 | for(int i = l; i >= 1; i /= 10) 41 | { 42 | tmp[site] = rest/i; 43 | if(i > 10 && rest%i/(i/10) == 0) dfs(rest%i, sum + rest/i, site+1, i/100,1);//判分割后余下的数是否有前导零 44 | else dfs(rest%i, sum + rest/i, site+1, i/10,p); 45 | } 46 | 47 | } 48 | 49 | int main() 50 | { 51 | int n; 52 | while(~scanf("%d %d",&t,&n) && (t+n)) 53 | { 54 | f = 0; 55 | len = 0; 56 | mm = -1; 57 | dfs(n,0,0,getlen(n),0); 58 | 59 | if(mm == -1) puts("error"); 60 | else if(f) puts("rejected"); 61 | else 62 | { 63 | printf("%d",mm); 64 | for(int i = 0; i < len; ++i) printf(" %d",num[i]); 65 | puts(""); 66 | } 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/深搜_A Knight's Journey.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 10; 6 | int p, q, way[maxn*maxn][2] = {0}, vis[maxn][maxn] = {0}; 7 | int dx[8]={-2,-2,-1,-1,1,1,2,2}, dy[8]={-1,1,-2,2,-2,2,-1,1}; // 8种走法 8 | 9 | int dfs(int tot, int rear, int x, int y) { 10 | if (rear == tot) return 1; 11 | else for(int i=0;i<8;i++){ 12 | int nx=x+dx[i],ny=y+dy[i]; 13 | if(nx>=0&&nx=0&&ny

3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int n, k, cnt; 8 | char arr[10][10]; int row[10], col[10], rec[10]; // rec[10]记录棋子放在第几行 9 | void dfs(int now) { // 当前排了几个棋子 10 | for (int i = rec[now-1]; i <= n; ++i) { 11 | for (int j = 1; j <= n; ++j) { 12 | if (arr[i][j] == '#' && !row[i] && !col[j]) { 13 | rec[now] = i; 14 | row[i] = col[j] = 1; 15 | if (now == k) ++cnt; 16 | else dfs(now+1); 17 | row[i] = col[j] = 0; 18 | } 19 | } 20 | } 21 | } 22 | 23 | int main() { 24 | while (scanf("%d %d", &n, &k) != EOF) { 25 | if (n == -1 && k == -1) break; 26 | fill(row, row+10, 0); fill(col, col+10, 0); 27 | for (int i = 1; i <= n; ++i) { 28 | for (int j = 1; j <= n; ++j) cin >> arr[i][j]; 29 | } 30 | cnt = 0; dfs(1); 31 | printf("%d\n", cnt); 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /北大程序设计与算法专项课程/算法基础/递归_完美覆盖.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 当n=0, 标准答案里将其设为f(0)=1; 3 | n为奇数时,无法实现完全覆盖,将其设为0; 4 | 其他情况下, 5 | f(2)=3, 6 | f(4)=3*f(2)+2, 7 | f(6)=3*f(4)+2*f(2)+2, 8 | f(n)=3*f(n-2)+2*(f(n-4)+f(n-6)+….+f(2))+2 = f(n-2)+2*(f(n-2)+f(n-4)+….+f(2))+2; 9 | 题目设定f(0)=1 可以推出 f(n) = 4 * f(n-2) - f(n-4) 10 | ***/ 11 | #include 12 | using namespace std; 13 | 14 | 15 | int main() { 16 | int n; 17 | cin >> n; 18 | while(n!=-1) { 19 | if (n%2) 20 | cout << 0 << endl; 21 | else if (n==0) 22 | cout << 1 << endl; 23 | else { 24 | long long last=0, last_sum=0, cur=3; 25 | for (int i=4; i<=n; i=i+2){ 26 | last = cur; 27 | last_sum += last; 28 | cur = 2*last_sum+last+2; 29 | } 30 | cout << cur << endl; 31 | } 32 | cin >> n; 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /浙大数据结构/第三周_树的同构.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct node { 5 | char element; 6 | int left, right; 7 | }tree1[10], tree2[10]; // 用静态链表存储树 8 | int check[10] = {0}; // 标记是否为子节点 9 | 10 | int buildTree() { // 返回根节点在静态链表中的索引 11 | int num; cin >> num; 12 | if (!num) return -1; 13 | int check[10] = {0}; 14 | for (int i = 0; i < num; ++i) { 15 | char tmp1, tmp2; 16 | cin >> tree[i].element >> tmp1 >> tmp2; 17 | if (tmp1 != '-') { 18 | tree[i].left = tmp1 - '0'; 19 | check[tree[i].left] = 1; 20 | } else tree[i].left = -1; 21 | if (tmp2 != '-') { 22 | tree[i].right = tmp2 - '0'; 23 | check[tree[i].right] = 1; 24 | } else tree[i].right = -1; 25 | } 26 | for (int i = 0; i < num; ++i) { // 找到根节点返回 27 | if (!check[i]) return i; 28 | } 29 | return -1; 30 | } 31 | 32 | bool isSame(int root1, int root2) { 33 | if (root1 == -1 && root2 == -1) return true; // 两棵树都是空的 34 | if (root1 == -1 || root2 == -1) return false; // 只有一棵树是空的 35 | if (tree1[root1].element != tree2[root2].element) return false; // 树1根节点值不等于树2根节点值 36 | // tree1[root1].left是下一个要判断的新根在静态链表中的索引 37 | if (tree1[tree1[root1].left].element == tree2[tree2[root2].left].element) return isSame(tree1[root1].right, tree2[root2].right); 38 | // 如果树1的左半边不等于树2的左半边 则左右交换比较 树1左对应树2右 树1右对应树1左 39 | else return isSame(tree1[root1].left, tree2[root2].right) && isSame(tree1[root1].right, tree2[root2].left); 40 | } 41 | 42 | int main() { 43 | int root1 = buildTree(tree1); 44 | int root2 = buildTree(tree2); 45 | if (isSame(root1, root2)) cout << "Yes" << endl; 46 | else cout << "No" << endl; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /浙大数据结构/第二周_线性结构_一元多项式的乘法与加法运算.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int n1, n2; 8 | map > poly; 9 | map > mul; 10 | map > sum; 11 | cin >> n1; 12 | while (n1--) { 13 | int co, ex; 14 | cin >> co >> ex; 15 | poly[ex] = co; 16 | sum[ex] += co; 17 | } 18 | cin >> n2; 19 | while (n2--) { 20 | int co, ex; 21 | cin >> co >> ex; 22 | // mul 23 | map::iterator it; 24 | for (it = poly.begin(); it != poly.end(); it++) { 25 | mul[it->first+ex] += it->second * co; 26 | } 27 | sum[ex] += co; 28 | } 29 | 30 | int cnt = 0; 31 | map::iterator it1; 32 | for (it1 = mul.begin(); it1 != mul.end(); it1++) { 33 | if (it1->second) { 34 | if (cnt) cout << ' '; 35 | cout << it1->second << ' ' << it1->first; 36 | cnt++; 37 | } 38 | 39 | } 40 | if (!cnt) cout << "0 0"; 41 | cout << endl; 42 | 43 | map::iterator it2; 44 | cnt = 0; 45 | for (it2 = sum.begin(); it2 != sum.end(); it2++) { 46 | if (it2->second) { 47 | if (cnt) cout << ' '; 48 | cout << it2->second << ' ' << it2->first; 49 | cnt++; 50 | } 51 | } 52 | if (!cnt) cout << "0 0"; 53 | cout << endl; 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /真题模拟/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/真题模拟/.DS_Store -------------------------------------------------------------------------------- /真题模拟/1031 Hello World for U.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | string s; cin >> s; 7 | int len = s.length(); int n = len + 2; 8 | int n1 = n/3, n2 = n/3, n3 = n/3; n2 += n % 3; 9 | int space = n2 - 2; 10 | for (int i = 0; i < n1-1; ++i) { 11 | cout << s[i]; 12 | for (int j = 0; j < space; ++j) cout << ' '; 13 | cout << s[len-1-i] << endl; 14 | } 15 | for (int i = n1-1; i < n1+n2-1; ++i) { 16 | cout << s[i]; 17 | } 18 | cout << endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /真题模拟/1032 Sharing.cpp: -------------------------------------------------------------------------------- 1 | // 投机取巧的我hiahia~ 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | const int maxn = 100010; int nexts[maxn], hashtable[maxn]; 7 | int head1, head2, n; scanf("%d %d %d", &head1, &head2, &n); 8 | if (head1 == head2) { 9 | printf("%05d\n", head1); return 0; 10 | } 11 | int address, next; char data; 12 | for (int i = 0; i < n; ++i) { 13 | scanf("%d %c %d", &address, &data, &next); 14 | nexts[address] = next; 15 | } 16 | int ans = -1; 17 | while(nexts[head1] != -1) { 18 | hashtable[nexts[head1]] = 1; 19 | head1 = nexts[head1]; 20 | } 21 | while (nexts[head2] != -1) { 22 | if (hashtable[nexts[head2]]) { 23 | ans = nexts[head2]; break; 24 | } 25 | else head2 = nexts[head2]; 26 | } 27 | if (ans == -1) printf("-1\n"); 28 | else printf("%05d\n", ans); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /真题模拟/1033 To Fill or Not to Fill.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct station { 6 | double price, distance; 7 | }stations[510]; 8 | 9 | bool cmp(station a, station b) { 10 | return a.distance < b.distance; 11 | } 12 | 13 | int main() { 14 | double cap, aimDistance, unitRun; int n; 15 | scanf("%lf %lf %lf %d", &cap, &aimDistance, &unitRun, &n); 16 | double FULLRUN = cap * unitRun; 17 | stations[n].price = 0; stations[n].distance = aimDistance; 18 | for (int i = 0; i < n; ++i) scanf("%lf %lf", &stations[i].price, &stations[i].distance); 19 | sort(stations, stations+n+1, cmp); 20 | if (stations[0].distance) { 21 | printf("The maximum travel distance = 0.00\n"); return 0; 22 | } 23 | double money = 0, nowGas = 0, needGas; int now = 0; 24 | while (now != n) { 25 | int minPrice = 1000100, minIndex = -1; 26 | for (int i = now+1; i <= n && stations[i].distance-stations[now].distance <= FULLRUN; ++i) { 27 | if (stations[i].price < minPrice) { 28 | minPrice = stations[i].price; minIndex = i; 29 | if (stations[i].price < stations[now].price) break; // 关键一步 30 | } 31 | } 32 | if (minIndex == -1) { 33 | printf("The maximum travel distance = %.2f\n", stations[now].distance + FULLRUN); 34 | return 0; 35 | } 36 | needGas = (stations[minIndex].distance - stations[now].distance) / unitRun; 37 | if (stations[minIndex].price < stations[now].price) { 38 | if (nowGas < needGas) { 39 | money += (needGas - nowGas) * stations[now].price; nowGas = 0; 40 | } 41 | else nowGas -= needGas; 42 | } 43 | else { 44 | money += (cap - nowGas) * stations[now].price; nowGas = cap - needGas; 45 | } 46 | now = minIndex; 47 | } 48 | printf("%.2f", money); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /真题模拟/1035 Password.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct stu { 7 | string name, pwd; 8 | }students[1010]; 9 | int hashtable[1010] = {0}; 10 | 11 | int main() { 12 | int n; cin >> n; 13 | for (int i = 0 ; i < n; ++i) { 14 | cin >> students[i].name >> students[i].pwd; 15 | for (int j = 0, len = students[i].pwd.length(); j < len; ++j) { 16 | switch (students[i].pwd[j]) { 17 | case '1': 18 | students[i].pwd[j] = '@'; 19 | hashtable[i] = 1; 20 | break; 21 | case '0': 22 | students[i].pwd[j] = '%'; 23 | hashtable[i] = 1; 24 | break; 25 | case 'l': 26 | students[i].pwd[j] = 'L'; 27 | hashtable[i] = 1; 28 | break; 29 | case 'O': 30 | students[i].pwd[j] = 'o'; 31 | hashtable[i] = 1; 32 | break; 33 | default: 34 | continue; 35 | } 36 | } 37 | } 38 | int cnt = accumulate(hashtable, hashtable+1000, 0); 39 | if (!cnt) { 40 | if (n==1) cout << "There is 1 account and no account is modified" << endl; 41 | else cout << "There are " << n << " accounts and no account is modified" << endl; 42 | } 43 | else { 44 | cout << cnt << endl; 45 | for (int i = 0; i < 1000; ++i) { 46 | if (hashtable[i]) cout << students[i].name << " " << students[i].pwd << endl; 47 | } 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /真题模拟/1036 Boys vs Girls.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct stu { 8 | string name, id; 9 | char gender; 10 | int grade; 11 | }; 12 | 13 | bool toSmall(stu a, stu b) { 14 | return a.grade > b.grade; 15 | } 16 | 17 | bool toBig(stu a, stu b) { 18 | return a.grade < b.grade; 19 | } 20 | int main() { 21 | int n; cin >> n; 22 | vector girls; vector boys; 23 | stu tmp; 24 | for (int i = 0; i < n; ++i) { 25 | cin >> tmp.name >> tmp.gender >> tmp.id >> tmp.grade; 26 | if (tmp.gender == 'F') girls.push_back(tmp); 27 | else boys.push_back(tmp); 28 | } 29 | if (!girls.size()) cout << "Absent" << endl; 30 | else { 31 | sort(girls.begin(), girls.end(), toSmall); cout << girls[0].name << " " << girls[0].id << endl; 32 | } 33 | if (!boys.size()) cout << "Absent" << endl; 34 | else { 35 | sort(boys.begin(), boys.end(), toBig); cout << boys[0].name << " " << boys[0].id << endl; 36 | } 37 | if (!girls.size() || !boys.size()) cout << "NA" << endl; 38 | else cout << girls[0].grade - boys[0].grade << endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /真题模拟/1037 Magic Coupon.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | bool toSmall(int a, int b) { 7 | return a > b; 8 | } 9 | 10 | int main() { 11 | vector positiveC, negativeC, positiveP, negativeP; 12 | int n, tmp; scanf("%d", &n); 13 | while(n--) { 14 | scanf("%d", &tmp); 15 | if (tmp > 0) positiveC.push_back(tmp); 16 | else if (tmp < 0) negativeC.push_back(tmp); 17 | } 18 | scanf("%d", &n); 19 | while (n--) { 20 | scanf("%d", &tmp); 21 | if (tmp > 0) positiveP.push_back(tmp); 22 | else if (tmp < 0) negativeP.push_back(tmp); 23 | } 24 | int money = 0; 25 | sort(positiveC.begin(), positiveC.end(), toSmall); sort(positiveP.begin(), positiveP.end(), toSmall); 26 | sort(negativeC.begin(), negativeC.end()); sort(negativeP.begin(), negativeP.end()); 27 | for (int i = 0, j = 0, len1 = positiveC.size(), len2 = positiveP.size(); i < len1 && j < len2; ++i, ++j) money += positiveC[i] * positiveP[j]; 28 | for (int i = 0, j = 0, len1 = negativeC.size(), len2 = negativeP.size(); i < len1 && j < len2; ++i, ++j) money += negativeC[i] * negativeP[j]; 29 | printf("%d\n", money); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /真题模拟/1038 Recover the Smallest Number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | bool cmp(string a, string b) { 7 | return a+b < b+a; 8 | } 9 | 10 | int main() { 11 | int n; cin >> n; 12 | string arr[10010]; 13 | for (int i = 0; i < n; ++i) cin >> arr[i]; 14 | sort(arr, arr+n, cmp); 15 | string ans = ""; 16 | for (int i = 0; i < n; ++i) ans += arr[i]; 17 | while (ans != "" && ans[0] == '0') ans.erase(0,1); 18 | if (ans == "") cout << 0 << endl; 19 | else cout << ans < 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | const int maxn = 1010; 10 | char bign[maxn] = {0}; 11 | 12 | bool isP(string str) { 13 | string rs = str; reverse(rs.begin(), rs.end()); 14 | if (rs == str) return true; 15 | else return false; 16 | } 17 | 18 | string addBign(string a, string b) { 19 | int len = a.length(), carry = 0; 20 | string ans = ""; 21 | for (int i = 0; i < len; ++i) { 22 | ans += to_string((a[i]-'0'+b[i]-'0'+carry) % 10); 23 | carry = (a[i]-'0'+b[i]-'0'+carry) / 10; 24 | } 25 | if (carry != 0) ans += to_string(carry); 26 | reverse(ans.begin(), ans.end()); 27 | return ans; 28 | } 29 | 30 | int main() { 31 | string s; cin >> s; int cnt = 0; 32 | while (!isP(s) && cnt < 10) { 33 | string rs = s; reverse(rs.begin(), rs.end()); 34 | cout << s << " + " << rs << " = "; 35 | s = addBign(s, rs); cout << s << endl; 36 | cnt++; 37 | } 38 | if (!isP(s)) cout << "Not found in 10 iterations." << endl; 39 | else cout << s << " is a palindromic number." << endl; 40 | return 0; 41 | } 42 | 43 | /*** 44 | 模拟反思: 45 | 一紧张代码风格就变纯c是什么毛病。。越写越难受 最后干脆全部删掉用c++重新来过 46 | 越是紧张越是抱牢C++的大腿呀!! 47 | 涉及字符串必须C++!!! 48 | I love C++!!!(^_^)v 49 | ***/ 50 | -------------------------------------------------------------------------------- /真题模拟/1152 Google Recruitment.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | bool isPrime(long long n) { 7 | if (n < 2) return false; 8 | if (n == 2) return true; 9 | int sqr = int(sqrt(n * 1.0)); 10 | for (int i = 2; i <= sqr; ++i) { 11 | if (n % i == 0) return false; 12 | } 13 | return true; 14 | } 15 | 16 | int main() { 17 | int l, k; cin >> l >> k; 18 | string num; cin >> num; 19 | for (int i = 0; i < l; ++i) { 20 | string tmp = num.substr(i, k); 21 | if (isPrime(stoll(tmp))) { 22 | cout << tmp << endl; return 0; 23 | } 24 | } 25 | cout << "404" << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /真题模拟/A1118_Birds in Forest.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 同一张照片里的鸟属于同一颗树 -> 并查集 3 | 树的数量 -> 父亲的数量 4 | 鸟的数量 -> hash标记 5 | 查鸟所属树 -> 查父亲 6 | ***/ 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | const int maxn = 10010; 12 | int father[maxn]; 13 | bool roots[maxn] = {0}, birds[maxn] = {0}; 14 | 15 | void init() { 16 | for (int i = 1; i < maxn; ++i) father[i] = i; 17 | } 18 | 19 | int findFather(int x) { 20 | int a = x; 21 | while (father[x] != x) x = father[x]; 22 | while (father[a] != a) { 23 | int b = a; 24 | a = father[a]; 25 | father[b] = x; 26 | } 27 | return x; 28 | } 29 | 30 | void unionFather(int a, int b) { 31 | int faA = findFather(a), faB = findFather(b); 32 | if (faA != faB) father[faA] = faB; 33 | } 34 | 35 | int main() { 36 | init(); 37 | int n; scanf("%d", &n); 38 | int treeNum = 0, birdNum = 0, k; 39 | while (n--) { 40 | scanf("%d", &k); int b; vector v; 41 | while (k--) { 42 | scanf("%d", &b); v.push_back(b); 43 | if (!birds[b]) { 44 | birdNum++; birds[b] = 1; 45 | } 46 | } 47 | for (int i = 1; i < v.size(); ++i) unionFather(v[i-1], v[i]); 48 | } 49 | for (int i = 1; i <= birdNum; ++i) { 50 | int r = findFather(i); 51 | if (!roots[r]) { 52 | treeNum++; roots[r] = 1; 53 | } 54 | } 55 | printf("%d %d\n", treeNum, birdNum); 56 | int q; scanf("%d", &q); 57 | int a, b; 58 | while (q--) { 59 | scanf("%d %d", &a, &b); 60 | if (findFather(a) == findFather(b)) printf("Yes\n"); 61 | else printf("No\n"); 62 | } 63 | return 0; 64 | } 65 | 66 | -------------------------------------------------------------------------------- /真题模拟/A1138_Postorder Traversal.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 树的先序遍历得到根 在中序遍历里根据根划分左右子树 3 | ***/ 4 | #include 5 | 6 | const int maxn = 50010; int n; 7 | int pre[maxn] = {0}, in[maxn] = {0}; 8 | 9 | bool flag = false; 10 | void create(int preL, int preR, int inL, int inR) { 11 | if (preL > preR || flag) return; // 序列为空直接返回 或已经找到最左端点 12 | int k; // 根在中序序列里的位置 13 | for (k = inL; k < inR; ++k) { 14 | if (in[k] == pre[preL]) break; 15 | } 16 | int leftNum = k - inL; 17 | create(preL+1, preL+leftNum, inL, k-1); 18 | create(preL+leftNum+1, preR, k+1, inR); 19 | if (!flag) { 20 | printf("%d\n", in[k]); flag = true; 21 | } 22 | } 23 | 24 | int main() { 25 | int n; scanf("%d", &n); 26 | for (int i = 0; i < n; ++i) scanf("%d", &pre[i]); 27 | for (int i = 0; i < n; ++i) scanf("%d", &in[i]); 28 | create(0, n-1, 0, n-1); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /真题模拟/A1139_First Contact.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const int maxn = 10000; 9 | unordered_map arr; // 标记一段关系(同性异性都有)是否存在 10 | struct node { 11 | int a, b; 12 | }; 13 | 14 | bool cmp(node x, node y) { 15 | return x.a != y.a ? x.a < y.a : x.b < y.b; 16 | } 17 | 18 | int main() { 19 | int n, m, k; 20 | scanf("%d %d", &n, &m); 21 | vector v[maxn]; // 只放同性朋友 22 | for (int i = 0; i < m; ++i) { 23 | string a, b; cin >> a >> b; 24 | int tmpa = abs(stoi(a)), tmpb = abs(stoi(b)); 25 | if (a.length() == b.length()) { // 每个人只能找自己的同性朋友传小纸条 26 | v[tmpa].push_back(tmpb); v[tmpb].push_back(tmpa); 27 | } 28 | arr[tmpa*maxn+tmpb] = arr[tmpb*maxn+tmpa] = true; // 这样就能在一个关键字里涵盖两个人的信息了 29 | } 30 | scanf("%d", &k); 31 | for (int i = 0; i < k; ++i) { 32 | int c, d; cin >> c >> d; 33 | c = abs(c); d = abs(d); 34 | vector ans; 35 | for (int j = 0; j < v[c].size(); ++j) { 36 | for (int k = 0; k < v[d].size(); ++k) { 37 | if (v[c][j] == d || v[d][k] == c) continue; 38 | if (arr[v[c][j]*maxn + v[d][k]]) ans.push_back(node{v[c][j], v[d][k]}); 39 | } 40 | } 41 | sort(ans.begin(), ans.end(), cmp); 42 | printf("%d\n", int(ans.size())); 43 | for (int j = 0; j < ans.size(); ++j) printf("%04d %04d\n", ans[j].a, ans[j].b); 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /真题模拟/A1140_Look-and-say Sequence.cpp: -------------------------------------------------------------------------------- 1 | // 从前往后读 当前字符与前一个字符pre相同的话累加cnt 2 | // 否则 之前字符串的后面加上to_string(cnt) cnt清零 pre等于现在的字符 3 | // 继续往后读 直到读到原来字符串的末尾 4 | // 以上操作做n次 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int main() { 10 | string d; int n; cin >> d >> n; 11 | n--; 12 | while (n--) { 13 | string newd = ""; int i = 0; 14 | while (i < d.length()) { 15 | char add = d[i]; 16 | newd += add; int cnt = 1; 17 | while (d[++i] == add && i < d.length()) cnt++; 18 | newd += to_string(cnt); 19 | } 20 | d = newd; 21 | } 22 | cout << d << endl; 23 | return 0; 24 | } 25 | 26 | /*** 27 | 没读清楚题目多循环了一轮 28 | 以为是自己写错了换了三种方法实现 29 | 二十分钟能AC的题折腾了快五十分钟md 30 | 31 | 逐!字!逐!句!读!题!目! 32 | ***/ 33 | -------------------------------------------------------------------------------- /真题模拟/A1141_PAT Ranking of Institutions.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 参赛选手人数n(<10^5) 接下来n行 3 | 字符串id(首位代表登记BAT) score 字符串school 4 | id是唯一的 5 | 6 | 输出学校总数 第一行 7 | 接下来升序输出学校排名 rank school tws 该校学生人数 8 | tws = int(ScoreB/1.5 + ScoreA + ScoreT*1.5) 9 | ScoreX is the total score of the testees belong to this institution on level X 10 | 按照tws升序排列 如果同分则排名相同 根据学生人数升序 如果还tie 按照校名字典序排列 11 | ***/ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | using namespace std; 21 | 22 | struct school { 23 | string name; 24 | int stuNum, tws; 25 | double scoreB, scoreA, scoreT; 26 | school() { 27 | scoreB = scoreA = scoreT = 0; 28 | stuNum = 0; 29 | } 30 | }; 31 | 32 | bool cmp(school a, school b) { 33 | if (a.tws != b.tws) return a.tws > b.tws; 34 | else if (a.stuNum != b.stuNum) return a.stuNum < b.stuNum; 35 | else return a.name < b.name; 36 | } 37 | 38 | vector v; 39 | map m; 40 | 41 | int main() { 42 | int n; scanf("%d", &n); 43 | string id, sch; double score; 44 | while (n--) { 45 | cin >> id >> score >> sch; 46 | for (int i = 0; i < sch.length(); ++i) sch[i] = tolower(sch[i]); 47 | char level = id[0]; 48 | if (level == 'B') m[sch].scoreB += score; 49 | else if (level == 'A') m[sch].scoreA += score; 50 | else if (level == 'T') m[sch].scoreT += score; 51 | m[sch].stuNum++; 52 | } 53 | map::iterator it = m.begin(); 54 | for (; it != m.end(); ++it) { 55 | (it->second).name = it->first; 56 | (it->second).tws = int((it->second).scoreB/1.5 + (it->second).scoreA + (it->second).scoreT*1.5); 57 | v.push_back(it->second); 58 | } 59 | cout << v.size() << endl; 60 | sort(v.begin(), v.end(), cmp); 61 | int rank = 1, pre = v[0].tws; 62 | for (int i = 0; i < v.size(); ++i) { 63 | if (v[i].tws != pre) { 64 | rank = i+1; pre = v[i].tws; 65 | } 66 | printf("%d %s %d %d\n", rank, v[i].name.c_str(), v[i].tws, v[i].stuNum); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /真题模拟/A1142_Maximal Clique.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 210; int nv, ne; 7 | int G[maxn][maxn] = {0}; 8 | 9 | bool judge1(vector q) { // 判断是否是clique 10 | for (int i = 0; i < q.size(); ++i) { 11 | for (int j = 0; j < q.size(); ++j) { 12 | if (q[i] == q[j]) continue; 13 | if (!G[q[i]][q[j]]) { 14 | return false; 15 | } 16 | } 17 | } 18 | return true; 19 | } 20 | 21 | bool judge2(vector q) { // 判断是否max即是否还有额外的点 22 | bool flag = false; 23 | for (int i = 1; i <= nv; ++i) { 24 | if (find(q.begin(), q.end(), i) != q.end()) continue; // 已在q中 25 | q.push_back(i); 26 | flag = judge1(q); 27 | if (flag) return flag; 28 | q.pop_back(); 29 | } 30 | return flag; 31 | } 32 | 33 | int main() { 34 | scanf("%d %d", &nv, &ne); 35 | int a, b; 36 | for (int i = 0; i < ne; ++i) { 37 | scanf("%d %d", &a, &b); 38 | G[a][b] = 1; G[b][a] = 1; 39 | } 40 | int m; scanf("%d", &m); int k, v; 41 | while (m--) { 42 | scanf("%d", &k); 43 | vector q; bool isC = true, notM = true; 44 | for (int i = 0; i < k; ++i) { 45 | scanf("%d", &v); q.push_back(v); 46 | } 47 | isC = judge1(q); 48 | if (!isC) { 49 | printf("Not a Clique\n"); continue; 50 | } 51 | notM = judge2(q); 52 | if (notM) { 53 | printf("Not Maximal\n"); continue; 54 | } 55 | printf("Yes\n"); 56 | } 57 | } 58 | 59 | /*** 60 | 模拟反思: 61 | 遇到新设定不要慌 用已有的知识一定可以解决 62 | 注意使用函数对功能的模块化 以便实代码的重用 63 | ***/ 64 | -------------------------------------------------------------------------------- /真题模拟/A1143_Lowest Common Ancestor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 10010; 6 | int pre[maxn]; 7 | // 开一个一万大小的哈希表有两个测试点过不了 8 | map hashtable; // 没有给定key取值范围的题目还是用map标记保险呀~ 9 | 10 | int main() { 11 | int m, n; scanf("%d %d", &m, &n); 12 | for (int i = 0; i < n; ++i) { 13 | scanf("%d", &pre[i]); hashtable[pre[i]] = 1; 14 | } 15 | int u, v; 16 | while (m--) { 17 | scanf("%d %d", &u, &v); 18 | int a = -1; // 祖先的值 19 | for (int i = 0; i < n; ++i) { 20 | a = pre[i]; 21 | if ((a >= u && a <= v) || (a >= v && a <= u)) break; 22 | } 23 | if (!hashtable[u] && !hashtable[v]) printf("ERROR: %d and %d are not found.\n", u, v); 24 | else if (!hashtable[u] || !hashtable[v]) printf("ERROR: %d is not found.\n", hashtable[u]?v:u); 25 | else if (a == u || a == v) printf("%d is an ancestor of %d.\n", a, a==u?v:u); 26 | else printf("LCA of %d and %d is %d.\n", u, v, a); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /真题模拟/A1144_The Missing Number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | int n; scanf("%d", &n); 7 | map mp; int tmp; 8 | for (int i = 0; i < n; ++i) { 9 | scanf("%d", &tmp); mp[tmp]++; 10 | } 11 | int num = 0; 12 | while(++num) { // 没给key取值范围 可能很大很大 就让while一直找嘛 13 | if (!mp[num]) { 14 | printf("%d\n", num); break; 15 | } 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /真题模拟/A1145_Hashing - Average Search Time .cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | bool isprime(int n) { 6 | int sqr = int(sqrt(n * 1.0)); 7 | for (int i = 2; i <= sqr; i++) 8 | if (n % i == 0) return false; 9 | return true; 10 | } 11 | int main() { 12 | int tsize, n, m, a; 13 | scanf("%d %d %d", &tsize, &n, &m); 14 | while(!isprime(tsize)) tsize++; 15 | vector v(tsize); 16 | for (int i = 0; i < n; i++) { 17 | scanf("%d", &a); 18 | int flag = 0; 19 | for (int j = 0; j < tsize; j++) { 20 | int pos = (a + j * j) % tsize; 21 | if (v[pos] == 0) { 22 | v[pos] = a; 23 | flag = 1; 24 | break; 25 | } 26 | } 27 | if (!flag) printf("%d cannot be inserted.\n", a); 28 | } 29 | int ans = 0; 30 | for (int i = 0; i < m; i++) { 31 | scanf("%d", &a); 32 | for (int j = 0; j <= tsize; j++) { 33 | ans++; 34 | int pos = (a + j * j) % tsize; 35 | if (v[pos] == a || v[pos] == 0) break; 36 | } 37 | } 38 | printf("%.1lf\n", ans * 1.0 / m); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /真题模拟/A1146_Topological Order.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 1010; 6 | vector adj[maxn]; 7 | int in[maxn] = {0}; // 记录每个顶点的入度 8 | 9 | 10 | int main() { 11 | int n, m; scanf("%d %d", &n, &m); 12 | int u, v; 13 | for (int i = 0; i < m; ++i) { 14 | scanf("%d %d", &u, &v); 15 | adj[u].push_back(v); in[v]++; 16 | } 17 | int k; scanf("%d", &k); 18 | vector ans; 19 | for (int q = 0; q < k; ++q) { 20 | vector tmpIn(in, in+maxn); // 拷贝一份入度数组的副本 21 | bool flag = true; 22 | for (int i = 0; i < 6; ++i) { 23 | scanf("%d", &u); 24 | if (tmpIn[u] != 0) flag = false; 25 | if (!flag) continue; 26 | for (int j = 0; j < adj[u].size(); ++j) tmpIn[adj[u][j]]--; 27 | } 28 | if (!flag) ans.push_back(q); 29 | } 30 | for (int i = 0; i < ans.size(); ++i) { 31 | printf("%d", ans[i]); 32 | if (i != ans.size()-1) printf(" "); 33 | else printf("\n"); 34 | } 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /真题模拟/A1147_Heaps .cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int m, n; 8 | void postOrder(int root, vector& v) { 9 | if (root > n) return; 10 | postOrder(2*root, v); // 注意完全二叉树这样获取左右节点序号的话 需要从1开始编号 11 | postOrder(2*root+1, v); 12 | if (root != 1) printf("%d ", v[root]); 13 | else printf("%d\n", v[root]); 14 | } 15 | 16 | int main() { 17 | scanf("%d %d", &m, &n); 18 | while (m--) { 19 | vector v(n+1); 20 | for (int i = 1; i <= n; ++i) scanf("%d", &v[i]); 21 | bool isMax = is_heap(v.begin()+1, v.end()); // 我怎么这么机智啊~hiahia~ 22 | bool isMin = is_heap(v.begin()+1, v.end(), greater()); 23 | if (isMax) printf("Max Heap\n"); 24 | else if (isMin) printf("Min Heap\n"); 25 | else printf("Not Heap\n"); 26 | postOrder(1, v); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /真题模拟/A1148_Werewolf - Simple Version.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | const int maxn = 110; int arr[maxn]; 8 | int n; scanf("%d", &n); 9 | for (int i = 1; i <= n; ++i) scanf("%d", &arr[i]); 10 | int w1 = -1, w2 = -1; // 两狼编号 11 | for (int i = 1; i <= n; ++i) { 12 | if (w1 != -1) break; 13 | for (int j = 1; j <= n; ++j) { // 枚举两狼为i j 14 | if (i == j) continue; 15 | int wliar = 0, hliar = 0; // 必须只有一狼一人撒谎 16 | for (int k = 1; k <= n; ++k) { // 枚举判定 17 | if (arr[k] < 0) { // 对狼的判定 18 | if (abs(arr[k]) != i && abs(arr[k]) != j) { // 说谎了 19 | if (k == i || k == j) wliar++; // 说谎的是狼 20 | else hliar++; 21 | } 22 | } 23 | else { // 对人的判定 24 | if (arr[k] == i || arr[k] == j) { // 说谎了 25 | if (k == i || k == j) wliar++; 26 | else hliar++; 27 | } 28 | } 29 | } 30 | if (wliar == 1 && hliar == 1) { 31 | w1 = i; w2 = j; break; 32 | } 33 | } 34 | } 35 | if (w1 == -1) printf("No Solution\n"); 36 | else printf("%d %d\n", w1, w2); 37 | return 0; 38 | } 39 | 40 | /*** 41 | 九月考乙级的时候被这道题搞的心态崩了 一直没敢回头看 42 | 现在模拟九月甲级 20来分钟写完一遍AC 43 | 真是 轻舟已过万重山~ 44 | 变强的感觉真好~ 45 | ***/ 46 | -------------------------------------------------------------------------------- /真题模拟/A1149_Dangerous Goods Packaging .cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | map > mp; // 每个物品编号对应一些它的相克物品合集 8 | void isValid() { 9 | int hashtable[1000000] = {0}; vector goods; 10 | int k, good; scanf("%d", &k); 11 | for (int i = 0; i < k; ++i) { 12 | scanf("%d", &good); goods.push_back(good); 13 | hashtable[good] = 1; 14 | } 15 | for (int i = 0; i < k; ++i) { 16 | for (int j = 0; j < mp[goods[i]].size(); ++j) { 17 | if (hashtable[ mp[goods[i]][j] ]) { 18 | printf("No\n"); return; 19 | } 20 | } 21 | } 22 | printf("Yes\n"); return; 23 | } 24 | 25 | int main() { 26 | int n, m; scanf("%d %d", &n, &m); 27 | int a, b; 28 | while (n--) { // 读取相克物品对 29 | scanf("%d %d", &a, &b); 30 | mp[a].push_back(b); mp[b].push_back(a); 31 | } 32 | while (m--) isValid(); 33 | return 0; 34 | } 35 | 36 | /*** 37 | 模拟反思 第一次用STL的find方法超时了一个测试点 38 | 就用哈希表在读入数据时判断 默认没有重复ID 结果答案错误了俩 39 | emmm还是不能抱有侥幸心理 除非题目给定 否则不要做主观预设 40 | ***/ 41 | -------------------------------------------------------------------------------- /真题模拟/A1150_Travelling Salesman Problem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 500, INF = 10<<9; 6 | int G[maxn][maxn] = {0}; 7 | 8 | int judge(int cities) { // 返回一条路径的距离 9 | int n; scanf("%d", &n); vector path(n); 10 | for (int i = 0; i < n; ++i) scanf("%d", &path[i]); 11 | int dis = 0; bool simple = true; 12 | bool vis[maxn] = {0}; vis[path[0]] = true; // 标记起点已经访问 13 | for (int i = 1; i < n; ++i) { 14 | if (!G[path[i-1]][path[i]]) { // 如果两点之间没有连通 15 | printf("NA (Not a TS cycle)\n"); return INF; 16 | } 17 | if (vis[path[i]] && i != n-1) simple = false; // 重复访问了节点 18 | vis[path[i]] = true; dis += G[path[i-1]][path[i]]; 19 | } 20 | int cnt = 0; 21 | for (int i = 1; i <= cities; ++i) cnt += vis[i]; 22 | if (cnt < cities || path[0] != path[n-1]) { 23 | printf("%d (Not a TS cycle)\n", dis); // 没有访问到所有的节点或者没有回到起点 24 | return INF; 25 | } 26 | else if (!simple) printf("%d (TS cycle)\n", dis); 27 | else printf("%d (TS simple cycle)\n", dis); 28 | return dis; 29 | } 30 | 31 | int main() { 32 | int n, m; scanf("%d %d", &n, &m); // n顶点数 m边数 33 | int u, v, dis; 34 | for (int i = 0; i < m; ++i) { 35 | scanf("%d %d %d", &u, &v, &dis); 36 | G[u][v] = dis; G[v][u] = dis; 37 | } 38 | int k; scanf("%d", &k); 39 | int minDis = INF, idx = -1; 40 | for (int i = 1; i <= k; ++i) { 41 | printf("Path %d: ", i); 42 | int tmp = judge(n); 43 | if (tmp < minDis) { 44 | minDis = tmp; idx = i; 45 | } 46 | } 47 | printf("Shortest Dist(%d) = %d\n", idx, minDis); 48 | return 0; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /真题模拟/A1151_LCA in a Binary Tree.cpp: -------------------------------------------------------------------------------- 1 | // 有个段错误扣了一分0 0? 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | const int maxn = 10010; 8 | int in[maxn], pre[maxn], pos[maxn]; 9 | // pos存储中序序列元素i的位置 u v位置在i/root两边 则i为lcs 都在左边 往左边找 右边亦然 10 | 11 | int u, v; 12 | void lfs(int preL, int preR, int inL, int inR) { 13 | if (preL > preR) return; 14 | int root = pre[preL]; int rootPos = pos[root]; // root在中序序列中位置 15 | int numLeft = rootPos - inL; 16 | if (pos[u] < rootPos && pos[v] < rootPos) lfs(preL+1,preL+numLeft, inL, rootPos-1); 17 | else if (pos[u] > rootPos && pos[v] > rootPos) lfs(preL+numLeft+1, preR, rootPos+1, inR); 18 | else if ((pos[u] < rootPos && pos[v] > rootPos) || 19 | (pos[v] < rootPos && pos[u] > rootPos) 20 | ) { 21 | printf("LCA of %d and %d is %d.\n", u, v, root); 22 | } 23 | else if (pos[u] == rootPos || pos[v] == rootPos) { 24 | printf("%d is an ancestor of %d.\n", root, u==root?v:u); 25 | } 26 | } 27 | 28 | int main() { 29 | fill(pos, pos+maxn, -1); // 初始化pos 30 | map mp; // 跟上次一样的坑 用数组直接映射某key值是否出现会爆 必须map 31 | int m, n; scanf("%d %d", &m, &n); 32 | for (int i = 0; i < n; ++i) { 33 | scanf("%d", &in[i]); pos[in[i]] = i; mp[in[i]] = true; 34 | } 35 | for (int i = 0; i < n; ++i) scanf("%d", &pre[i]); 36 | while (m--) { 37 | scanf("%d %d", &u, &v); 38 | if (!mp[u] && !mp[v]) printf("ERROR: %d and %d are not found.\n", u ,v); 39 | else if (!mp[u] || !mp[v]) printf("ERROR: %d is not found.\n", !mp[u]?u:v); 40 | else lfs(0, n-1, 0, n-1); 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /算法笔记/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/算法笔记/.DS_Store -------------------------------------------------------------------------------- /算法笔记/A1001_A+B Format.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int a, b; cin >> a >> b; 8 | b += a; 9 | if (b < 0) { 10 | cout << '-'; 11 | b = 0 - b; 12 | } 13 | string sb = to_string(b); 14 | int len = sb.length(); 15 | if (len < 4) { 16 | cout << sb << endl; return 0; 17 | } 18 | int num = len % 3; 19 | if (!num) num = 3; 20 | for (int i = 0; i < len; ++i) { 21 | cout << sb[i]; 22 | if (i == num-1 && i != len-1) { 23 | cout << ','; num += 3; 24 | } 25 | } 26 | cout << endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /算法笔记/A1004_Counting Leaves .cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int N = 110; 7 | 8 | vector G[N]; // 存放树 9 | int leaf[N] = {0}; // 存放每层的叶子节点个数 10 | int max_h = 1; // 树的深度 11 | 12 | void DFS(int index, int h) { 13 | max_h = max(h, max_h); 14 | if (G[index].empty()) { 15 | leaf[h]++; return; 16 | } 17 | for (int i = 0; i < G[index].size(); ++i) { 18 | DFS(G[index][i], h+1); 19 | } 20 | } 21 | 22 | int main() { 23 | int n, m, parent, child, k; 24 | scanf("%d %d", &n, &m); 25 | for (int i = 0; i < m; ++i) { 26 | scanf("%d %d", &parent, &k); 27 | for (int j = 0; j < k; ++j) { 28 | scanf("%d", &child); G[parent].push_back(child); 29 | } 30 | } 31 | DFS(1,1); 32 | printf("%d", leaf[1]); // 根节点是1层的叶子节点 33 | for (int i = 2; i <= max_h; ++i) printf(" %d", leaf[i]); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /算法笔记/A1005_Spell It Right .cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | string num; cin >> num; 7 | int sum = 0; 8 | for (int i = 0; i < num.length(); ++i) sum += num[i] - '0'; 9 | string arr[] = { 10 | "zero", 11 | "one", 12 | "two", 13 | "three", 14 | "four", 15 | "five", 16 | "six", 17 | "seven", 18 | "eight", 19 | "nine", 20 | }; 21 | string ssum = to_string(sum); 22 | for (int i = 0; i < ssum.length(); ++i) { 23 | if (i) cout << ' '; 24 | cout << arr[ssum[i]-'0']; 25 | } 26 | cout << endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /算法笔记/A1007_Maximum Subsequence Sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | const int maxn = 10010; 3 | int a[maxn], dp[maxn]; // a[i]存放序列 dp[i]存放以i为结尾的连续序列最大和 4 | int s[maxn] = {0}; // s[i]表示产生dp[i]的连续序列是从a的哪一个元素开始的 5 | 6 | int main() { 7 | int n; scanf("%d", &n); 8 | bool flag = false; // 标记数组中是否有非负数 9 | for (int i = 0; i < n; ++i) { 10 | scanf("%d", &a[i]); 11 | if (a[i] >= 0) flag = true; 12 | } 13 | if (!flag) { 14 | printf("0 %d %d\n", a[0], a[n-1]); return 0; 15 | } 16 | dp[0] = a[0]; // 边界 17 | for (int i = 1; i < n; ++i) { 18 | if (dp[i-1]+a[i] > a[i]) { 19 | dp[i] = dp[i-1] + a[i]; s[i] = s[i-1]; 20 | } 21 | else { 22 | dp[i] = a[i]; s[i] = i; 23 | } 24 | } 25 | int k = 0; // k最优解元素的数组索引 26 | for (int i = 1; i < n; ++i) { 27 | if (dp[i] > dp[k]) k = i; 28 | } 29 | printf("%d %d %d\n", dp[k], a[s[k]], a[k]); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /算法笔记/A1008_Elevator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int n; scanf("%d", &n); 6 | int arr[110]; 7 | for (int i = 0; i < n; ++i) scanf("%d", &arr[i]); 8 | int before = 0, time = 0; 9 | for (int i = 0; i < n; ++i) { 10 | if (arr[i] > before) time += 6 * (arr[i] - before); 11 | else if (arr[i] < before) time += 4 * (before - arr[i]); 12 | time += 5; 13 | before = arr[i]; 14 | } 15 | printf("%d\n", time); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /算法笔记/A1012_The Best Rank.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int ranks[1000000][4] = {0}; // 空间换时间 为了高效索引;按优先级存储 ranka rankc rankm ranke 6 | int subjectindex; 7 | char subject[4] = {'A', 'C', 'M', 'E'}; 8 | 9 | struct stu { 10 | int id; 11 | int grade[4]; // 也按优先级存储 12 | }; 13 | 14 | bool cmp(stu a, stu b) { 15 | return a.grade[subjectindex] > b.grade[subjectindex]; 16 | } 17 | 18 | int main() { 19 | int n, m; cin >> n >> m; 20 | stu students[n]; 21 | for (int i = 0; i < n; ++i) { 22 | int total = 0; 23 | cin >> students[i].id; 24 | for (int j = 1; j < 4; ++j) { 25 | cin >> students[i].grade[j]; total += students[i].grade[j]; 26 | } 27 | students[i].grade[0] = total; // 大家平均数的分母都是4 取分子就行了 28 | } 29 | 30 | for (subjectindex = 0; subjectindex < 4; ++subjectindex) { // 填ranks 31 | sort(students, students+n, cmp); 32 | int rank = 1, premark = students[0].grade[subjectindex]; 33 | for (int j = 0; j < n; ++j) { 34 | if (students[j].grade[subjectindex] != premark) { 35 | rank = j + 1; 36 | premark = students[j].grade[subjectindex]; 37 | } 38 | ranks[students[j].id][subjectindex] = rank; 39 | } 40 | } 41 | 42 | for (int i = 0; i < m; ++i) { 43 | int tmp; cin >> tmp; 44 | if (!ranks[tmp][0]) cout << "N/A" << endl; 45 | else { 46 | int minindex = 0; 47 | for (int j = 0; j < 4; ++j) { 48 | if (ranks[tmp][j] < ranks[tmp][minindex]) minindex = j; 49 | } 50 | cout << ranks[tmp][minindex] << ' ' << subject[minindex] << endl; 51 | } 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /算法笔记/A1013_Battle Over Cities.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 输入城市总数n 可用边数m 可能被毁掉的城市数量k 3 | 输出对每一个被毁掉的城市 需要重建的路的数量 4 | 5 | 本质就是一个连通图 被摘了一个节点b 同时摘除b周围的边 6 | 问需要几条边让这个图重新全连通 7 | 如何计算边呢? 8 | 把断裂的图看成一个个连通块 两个连通块之间只需一条边就能连接 这种连法一定是最少的 9 | 所以需要的边数就是连通块个数减一 10 | 如何取得连通块数量? 11 | 图的遍历 遍历连通块 12 | ***/ 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | const int maxn = 1010; 19 | vector G[maxn]; // 邻接表 20 | bool vis[maxn] = {false}; 21 | 22 | int currentPoint; // 当前要被删除的节点 23 | void dfs(int v) { 24 | if (v == currentPoint) return; // 当遍历到已删除的节点 25 | vis[v] = true; 26 | for (int i = 0; i < G[v].size(); ++i) { 27 | if (!vis[G[v][i]]) dfs(G[v][i]); 28 | } 29 | } 30 | 31 | int main() { 32 | int n, m, k; 33 | scanf("%d %d %d", &n, &m, &k); 34 | for (int i = 0; i < m; ++i) { 35 | int a, b; scanf("%d %d", &a, &b); 36 | G[a].push_back(b); G[b].push_back(a); 37 | } 38 | for (int q = 0; q < k; ++q) { 39 | scanf("%d", ¤tPoint); 40 | memset(vis, false, sizeof(vis)); 41 | int block = 0; 42 | for (int i = 1; i <= n; ++i) { 43 | if (i != currentPoint && !vis[i]) { 44 | dfs(i); block++; 45 | } 46 | } 47 | printf("%d\n", block-1); 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /算法笔记/A1015_Reversible Primes.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 把数字n转成d进制dn 3 | 逆转dn 得到数字rdn //转换进制中直接得到rdn 4 | rdn转换成十进制的rn 5 | n和rn都为素数时输出Yes 6 | ***/ 7 | #include 8 | #include 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | string toD(int n, int d) { 14 | string rdn = ""; 15 | while (n) { 16 | rdn += to_string(n % d); n /= d; 17 | } 18 | return rdn; 19 | } 20 | 21 | int to10(string rdn, int d) { 22 | int rn = 0, len = rdn.length(), mul = 1; 23 | for (int i = len-1; i >= 0; --i) { 24 | rn += (rdn[i] - '0') * mul; mul *= d; 25 | } 26 | return rn; 27 | } 28 | 29 | bool isPrime(int n) { 30 | if (n < 2) return false; 31 | int sqr = int(sqrt(1.0 * n)); 32 | for (int i = 2; i <= sqr; ++i) { 33 | if (n % i == 0) return false; 34 | } 35 | return true; 36 | } 37 | 38 | int main() { 39 | int n, d; 40 | while (true) { 41 | cin >> n; if (n < 0) return 0; 42 | cin >> d; 43 | int rn = to10(toD(n, d), d); 44 | if (isPrime(n) && isPrime(rn)) cout << "Yes" << endl; 45 | else cout << "No" << endl; 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /算法笔记/A1017_Queueing at Bank.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | struct node { 6 | int come, time; 7 | } tempcustomer; 8 | bool cmp1(node a, node b) { 9 | return a.come < b.come; 10 | } 11 | int main() { 12 | int n, k; 13 | scanf("%d%d", &n, &k); 14 | vector custom; 15 | for(int i = 0; i < n; i++) { 16 | int hh, mm, ss, time; 17 | scanf("%d:%d:%d %d", &hh, &mm, &ss, &time); 18 | int cometime = hh * 3600 + mm * 60 + ss; 19 | if(cometime > 61200) continue; 20 | tempcustomer = {cometime, time * 60}; 21 | custom.push_back(tempcustomer); 22 | } 23 | sort(custom.begin(), custom.end(), cmp1); 24 | vector window(k, 28800); 25 | double result = 0.0; 26 | for(int i = 0; i < custom.size(); i++) { 27 | int tempindex = 0, minfinish = window[0]; 28 | for(int j = 1; j < k; j++) { 29 | if(minfinish > window[j]) { 30 | minfinish = window[j]; 31 | tempindex = j; 32 | } 33 | } 34 | if(window[tempindex] <= custom[i].come) { 35 | window[tempindex] = custom[i].come + custom[i].time; 36 | } else { 37 | result += (window[tempindex] - custom[i].come); 38 | window[tempindex] += custom[i].time; 39 | } 40 | } 41 | if(custom.size() == 0) 42 | printf("0.0"); 43 | else 44 | printf("%.1f", result / 60.0 / custom.size()); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /算法笔记/A1019_General Palindromic Number.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int n, b; cin >> n >> b; 6 | int arr[40]; // 最低进制是2 n取值范围<=10^9 2的32次方就有10^9了吧 再乘16 7 | int cnt = 0; 8 | do { 9 | arr[cnt++] = n % b; 10 | n /= b; 11 | } while(n); 12 | int front = 0, rear = cnt-1; 13 | bool isP = true; 14 | for (; front != rear; ++front, --rear) { 15 | if (arr[front] != arr[rear]) { 16 | isP = false; 17 | break; 18 | } 19 | } 20 | if (isP) cout << "Yes" << endl; 21 | else cout << "No" << endl; 22 | for (int j = cnt-1; j >= 0; --j) { 23 | if (j != cnt-1) cout << ' '; 24 | cout << arr[j]; 25 | } 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /算法笔记/A1020_Tree Traversals.cpp: -------------------------------------------------------------------------------- 1 | // 先根据后序和中序建树 再进行层序遍历 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct node { 7 | int data; 8 | node* left; 9 | node* right; 10 | }; 11 | 12 | const int maxn = 35; 13 | int post[35], in[35]; 14 | 15 | node* createTree(int postL, int postR, int inL, int inR) { 16 | if (postL > postR) return NULL; // 如果序列为空 17 | node* root = new node; 18 | root->data = post[postR]; 19 | int k; // root在中序序列中的位置 20 | for (k = inL; k <= inR; ++k) { 21 | if (in[k] == root->data) break; 22 | } 23 | int numLeft = k - inL; // 左子树的节点个数 24 | // 左子树的后序序列区间为[postL, postL+numLeft-1] 中序序列区间为[inL, k-1] 25 | root->left = createTree(postL, postL+numLeft-1, inL, k-1); 26 | // 右子树的后序序列区间为[postL+numLeft, postR-1] 中序序列区间为[k+1, inR]; 27 | root->right = createTree(postL+numLeft, postR-1, k+1, inR); 28 | return root; 29 | } 30 | 31 | void layerOrder(node* root) { // 用queue遍历 32 | queue Q; 33 | Q.push(root); 34 | bool isFirst = true; 35 | while (!Q.empty()) { 36 | node* fro = Q.front(); 37 | Q.pop(); 38 | if (isFirst) { 39 | printf("%d", fro->data); isFirst = false; 40 | } 41 | else printf(" %d", fro->data); 42 | if (fro->left != NULL) Q.push(fro->left); 43 | if (fro->right != NULL) Q.push(fro->right); 44 | } 45 | } 46 | 47 | int main() { 48 | int n; scanf("%d", &n); 49 | for (int i = 0; i < n; ++i) scanf("%d", &post[i]); 50 | for (int i = 0; i < n; ++i) scanf("%d", &in[i]); 51 | node* root = createTree(0, n-1, 0, n-1); 52 | layerOrder(root); printf("\n"); 53 | delete []root; 54 | return 0; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /算法笔记/A1021_Deepest Root .cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 注意IO格式~~!一行一个啊喂 3 | 4 | 判断树是否为图:只有一个连通块 -> 用并查集判断 5 | 如果不是图 输出连通块(connected components)数量 6 | ***/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | const int maxn = 100010; 14 | vector G[maxn]; 15 | 16 | int isRoot[maxn] = {0}; 17 | int father[maxn]; 18 | 19 | int findFather(int x) { 20 | int a = x; 21 | while (x != father[x]) x = father[x]; 22 | while (a != father[a]) { 23 | int b = a; 24 | a = father[a]; 25 | father[b] = x; // 要等a从father[a]移走了才能对原来的father[a]做操作 26 | } 27 | return x; 28 | } 29 | 30 | void unionFather(int a, int b) { 31 | int faA = findFather(a), faB = findFather(b); 32 | if (faA != faB) father[faA] = faB; 33 | } 34 | 35 | int cntBlock(int n) { 36 | int block = 0; 37 | for (int i = 1; i <= n; ++i) isRoot[findFather(i)] = 1; 38 | for (int i = 1; i <= n; ++i) block += isRoot[i]; 39 | return block; 40 | } 41 | 42 | int maxH = 0; 43 | vector tmp, ans; // tmp存放临时DFS最远节点结果 ans保存答案 44 | void DFS(int u, int height, int pre) { // pre是u的父节点 防止走回头路 45 | if (height > maxH) { 46 | tmp.clear(); tmp.push_back(u); 47 | maxH = height; 48 | } 49 | else if (height == maxH) tmp.push_back(u); 50 | for (int i = 0; i < G[u].size(); ++i) { // 遍历u的所有子节点 51 | if (G[u][i] == pre) continue; // 由于是无向图 跳过回去的边 52 | DFS(G[u][i], height+1, u); 53 | } 54 | } 55 | 56 | int main() { 57 | int a, b, n; scanf("%d", &n); 58 | for (int i = 1; i <= n; ++i) father[i] = i; 59 | for (int i = 1; i < n; ++i) { 60 | scanf("%d %d", &a, &b); 61 | G[a].push_back(b); G[b].push_back(a); 62 | unionFather(a, b); 63 | } 64 | int block = cntBlock(n); 65 | if (block != 1) printf("Error: %d components\n", block); 66 | else { 67 | DFS(1, 1, -1); 68 | ans = tmp; 69 | DFS(ans[0], 1, -1); 70 | for (int i = 0; i < tmp.size(); ++i) ans.push_back(tmp[i]); 71 | sort(ans.begin(), ans.end()); 72 | printf("%d\n", ans[0]); 73 | for (int i = 1; i < ans.size(); ++i) { 74 | if (ans[i] != ans[i-1]) printf("%d\n", ans[i]); 75 | } 76 | } 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /算法笔记/A1022_Digital Library.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | IO说明: 3 | 第一行 书的总数N(<=10000) 接下来N*6行 4 | 书的7位ID 5 | 书名字符串 6 | 作者名字符串 (只有一位作者) 7 | 书的关键词们 以空格分隔 (<=5个) 8 | 出版商字符串 9 | 出版年份【1000,3000】 10 | (总关键词不超过1000个 总出版社不超过1000个 书的信息输入完成后) 11 | M 查询总数(<=1000) 接下来M行 每行采取以下一种查询方式 12 | 1: 书名 13 | 2: 作者名 14 | 3: 关键词 15 | 4: 出版商名 16 | 5: a 4-digit number representing the year 17 | 18 | 对每一条查询 首先输出原始查询语句 19 | 按升序输出查到的书ID 每个ID占一行 20 | 如果没找到 输出 Not Found 21 | ***/ 22 | 23 | // 思路:空间换时间 对每一种查询方式都建立一个map string-set 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | using namespace std; 30 | 31 | void query(map >& mp, string& q) { 32 | if (mp.find(q) == mp.end()) printf("Not Found\n"); 33 | else { 34 | set::iterator it; 35 | for(it = mp[q].begin(); it != mp[q].end(); ++it) printf("%07d\n", *it); 36 | } 37 | } 38 | 39 | int main() { 40 | int n; cin >> n; 41 | map > title2id, author2id, key2id, publish2id, year2id; 42 | int id; string tmp; 43 | while (n--) { 44 | cin >> id; char c = getchar(); 45 | getline(cin, tmp); title2id[tmp].insert(id); 46 | getline(cin, tmp); author2id[tmp].insert(id); 47 | while (cin >> tmp) { 48 | key2id[tmp].insert(id); 49 | c = getchar(); 50 | if (c == '\n') break; 51 | } 52 | getline(cin, tmp); publish2id[tmp].insert(id); 53 | cin >> tmp; year2id[tmp].insert(id); 54 | } 55 | int m; cin >> m; int tag; string q; 56 | while (m--) { 57 | scanf("%d: ", &tag); getline(cin, q); 58 | cout << tag << ": " << q << endl; 59 | set::iterator it; 60 | switch (tag) { 61 | case 1: 62 | query(title2id, q); break; 63 | case 2: 64 | query(author2id, q); break; 65 | case 3: 66 | query(key2id, q); break; 67 | case 4: 68 | query(publish2id, q); break; 69 | case 5: 70 | query(year2id, q); break; 71 | } 72 | } 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /算法笔记/A1023_Have Fun with Numbers.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 大数运算之高精度数乘低精度数 3 | 建立大数结构体 用数组存储数位 len存储数位长度 4 | 建立哈希表 初始值为0 存储大数数位的个数 5 | 高精度数双倍函数 6 | ***/ 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | struct bign { 12 | int digit[50], len; 13 | bign() { 14 | len = 0; memset(digit, 0, sizeof(digit)); 15 | } 16 | }; 17 | 18 | bign assign(char arr[]) { 19 | bign a; a.len = strlen(arr); 20 | for (int i = 0; i < a.len; ++i) { 21 | a.digit[i] = arr[a.len-1-i] - '0'; 22 | } 23 | return a; 24 | } 25 | 26 | bign doubleMul(bign a) { 27 | bign ans; int carry = 0; 28 | for (int i = 0; i < a.len; ++i) { 29 | int tmp = a.digit[i] * 2 + carry; 30 | ans.digit[i] = tmp % 10; ans.len++; carry = tmp / 10; 31 | } 32 | while (carry != 0) { 33 | ans.digit[ans.len++] = carry % 10; carry /= 10; 34 | } 35 | return ans; 36 | } 37 | 38 | void printBign(bign a) { 39 | for (int i = a.len-1; i >= 0; --i) printf("%d", a.digit[i]); 40 | printf("\n"); 41 | } 42 | 43 | int main() { 44 | char str[21] = {0}; scanf("%s", str); 45 | int hashtable[10] = {0}; 46 | for (int i = 0, len = strlen(str); i < len; ++i) hashtable[str[i] - '0']++; 47 | bign n = assign(str); bign doubleN = doubleMul(n); 48 | bool flag = true; 49 | for (int i = 0; i < doubleN.len; ++i) { 50 | if (!hashtable[doubleN.digit[i]]) { 51 | flag = false; break; 52 | } else hashtable[doubleN.digit[i]]--; 53 | } 54 | if (flag) printf("Yes\n"); 55 | else printf("No\n"); 56 | printBign(doubleN); 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /算法笔记/A1024_Palindromic Number.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | while n不是回文数 做操作 step++ 3 | step > maxstep 退出循环 4 | ***/ 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | struct bign { 10 | int digit[1000], len; 11 | bign() { 12 | memset(digit, 0, sizeof(digit)); len = 0; 13 | } 14 | }; 15 | 16 | bign change(char str[]) { 17 | bign a; a.len = strlen(str); 18 | for (int i = 0; i < a.len; ++i) a.digit[i] = str[a.len-1-i] - '0'; 19 | return a; 20 | } 21 | 22 | bign add(bign a, bign b) { 23 | bign ans; int carry = 0; 24 | for(int i=0;i= 0; --i) printf("%d", a.digit[i]); 35 | printf("\n"); 36 | } 37 | 38 | bool isPalin(int arr[], int len) { 39 | if (arr[len-1]==0) return false; 40 | if (arr[0]==0) return false; 41 | for (int i = 0, half = len/2; i < half; ++i) { 42 | if (arr[i] != arr[len-1-i]) return false; 43 | } 44 | return true; 45 | } 46 | 47 | bign operate(bign a) { 48 | bign ra; ra.len = a.len; 49 | for (int i = 0; i < a.len; ++i) ra.digit[i] = a.digit[a.len-1-i]; 50 | return add(a, ra); 51 | } 52 | 53 | int main() { 54 | char tmp[1000] = {0}; int k, step = 0; 55 | scanf("%s %d", tmp, &k); 56 | bign a = change(tmp); 57 | while (!isPalin(a.digit, a.len) && step < k) { 58 | a = operate(a); step++; 59 | } 60 | printBigN(a); printf("%d\n", step); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /算法笔记/A1025_PAT Ranking.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct tee { 8 | int place; 9 | string index; 10 | int mark, locrank; 11 | }; 12 | 13 | bool cmp(tee t1, tee t2) { 14 | if (t1.mark != t2.mark) return t1.mark > t2.mark; 15 | return t1.index < t2.index; 16 | } 17 | 18 | int main() { 19 | int n; cin >> n; 20 | vector v; 21 | for (int i = 1; i <= n; ++i) { // n个考场 22 | int k; cin >> k; // 每个考场k个人 23 | tee tmp; tmp.place = i; // 该考场每个考生的考场号都是i 24 | tee tees[k]; 25 | for (int j = 0; j < k; ++j) { // 读入考生证件号和考分 26 | cin >> tmp.index >> tmp.mark; 27 | tees[j] = tmp; // 每一位考生信息存在数组里 28 | } 29 | sort(tees, tees+k, cmp); 30 | int rank = 1, premark = tees[0].mark; // 两个并列第一的话就没有第二了 还是要仔细观察用例 不能想当然 31 | for (int j = 0; j < k; ++j) { 32 | if (tees[j].mark != premark) { // 一段同分考生后的第一位考生 其排名等于在数组中的位置 因为数组已经有序 33 | rank = j+1; premark = tees[j].mark; // 数组从0开始计数 所以j+1 34 | } 35 | tees[j].locrank = rank; 36 | v.push_back(tees[j]); 37 | } 38 | } 39 | cout << v.size() << endl; 40 | sort(v.begin(), v.end(), cmp); 41 | vector::iterator it = v.begin(); 42 | int rank = 1, premark = v[0].mark, cnt = 0; // cnt相当于j+1 43 | for (; it != v.end(); ++it) { 44 | cnt++; 45 | if ((*it).mark != premark) { 46 | rank = cnt; premark = (*it).mark; 47 | } 48 | cout << (*it).index << ' ' << rank << ' ' << (*it).place << ' ' << (*it).locrank << endl; 49 | } 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /算法笔记/A1027_Colors in Mars.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | string cal(int n) { 8 | string ans = ""; 9 | do { // 为了覆盖0的情况 进制转化一定要用do while 10 | int tmp = n % 13; 11 | if (tmp < 10) ans += '0' + tmp; 12 | else ans += 'A' + (tmp - 10); 13 | n /= 13; 14 | } while (n); 15 | reverse(ans.begin(), ans.end()); 16 | if (ans.length() == 1) ans = '0' + ans; 17 | return ans; 18 | } 19 | 20 | int main() { 21 | int tmp; 22 | cout << '#'; 23 | for (int i = 0; i < 3; ++i) { 24 | cin >> tmp; 25 | cout << cal(tmp); 26 | } 27 | cout << endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /算法笔记/A1028_List Sorting.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | vector students; 3 | students.resize(n); 4 | ***/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | int c; 13 | struct stu { 14 | string inf[3]; // 按序存储id name grade 15 | }; 16 | 17 | bool cmp(stu a, stu b) { 18 | if (a.inf[c] != b.inf[c]) return a.inf[c] < b.inf[c]; 19 | else return a.inf[0] < b.inf[0]; 20 | } 21 | 22 | int main() { 23 | int n = 0; scanf("%d %d", &n, &c); 24 | c--; // 因为索引 所以-1 25 | // stu students[n]; 这样写会导致段错误 26 | vector students; 27 | students.resize(n); 28 | for (int i = 0; i < n; ++i) { 29 | for (int j = 0; j < 3; ++j) { 30 | char tmp[10]; scanf("%s", tmp); 31 | students[i].inf[j] = tmp; 32 | } 33 | } 34 | if (n == 1) { 35 | for (int j = 0; j < 3; ++j) { 36 | if (j) printf(" "); 37 | printf("%s", students[0].inf[j].c_str()); 38 | } 39 | prinf("\n"); return 0; 40 | } 41 | sort(students, students+n, cmp); 42 | for (int i = 0; i < n; ++i) { 43 | for (int j = 0; j < 3; ++j) { 44 | if (j) printf(" "); 45 | printf("%s", students[i].inf[j].c_str()); 46 | } 47 | printf("\n"); 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /算法笔记/A1029_Median.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int Max = 1000001; 4 | int a[Max]; 5 | int main(){ 6 | int n, m; 7 | scanf("%d", &n); 8 | for(int k = 0; k < n; ++k) 9 | scanf("%d", &a[k]); 10 | scanf("%d", &m); 11 | a[n] = (1<<31) -1; 12 | int mid = (n+m -1)/2; 13 | int cnt = 0, i = 0, j= 0, b = 0; 14 | if(m > 0){scanf("%d", &b);} 15 | while(cnt < mid){ 16 | if(j >= m) b = (1<<31) -1; 17 | if(a[i] < b)i++; 18 | else {scanf("%d", &b);j++;} 19 | cnt++; 20 | } 21 | printf("%d\n", ((a[i] 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 510; 7 | const int INF = 10 << 9; 8 | 9 | // n为顶点数 m为边书 st和ed分别为起点和终点 10 | // G为距离矩阵 cost为花费矩阵 11 | // d[]记录最短距离 c[]记录最小花费 12 | int n, m, st, ed, G[maxn][maxn], cost[maxn][maxn]; 13 | int d[maxn], c[maxn], pre[maxn]; 14 | bool vis[maxn] = {false}; 15 | 16 | void Dijkstr(int s) { // s为起点 17 | fill(d, d + maxn, INF); 18 | fill(c, c + maxn, INF); 19 | for (int i = 0; i < n; ++i) pre[i] = i; 20 | d[s] = 0; c[s] = 0; 21 | for (int i = 0; i < n; ++i) { 22 | int u = -1, MIN = INF; 23 | for (int j = 0; j < n; ++j) { 24 | if (!vis[j] && d[j] < MIN) { // 找到未访问节点中d[]最小的 25 | u = j; MIN = d[u]; 26 | } 27 | } 28 | if (u == -1) return; 29 | vis[u] = true; 30 | for (int v = 0; v < n; ++v) { // 更新以u为中介可以优化的最短路径 31 | if (!vis[v] && G[u][v] != INF) { 32 | if (d[u] + G[u][v] < d[v]) { 33 | d[v] = d[u] + G[u][v]; 34 | c[v] = c[u] + cost[u][v]; 35 | pre[v] = u; 36 | } 37 | else if (d[u] + G[u][v] == d[v]) { 38 | if (c[u] + cost[u][v] < c[v]) { 39 | c[v] = c[u] + cost[u][v]; 40 | pre[v] = u; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | void DFS(int v) { // 打印路径 49 | if (v == st) { 50 | printf("%d ", v); return; 51 | } 52 | DFS(pre[v]); 53 | printf("%d ", v); 54 | } 55 | 56 | int main() { 57 | scanf("%d %d %d %d", &n, &m, &st, &ed); 58 | int u, v; 59 | fill(G[0], G[0] + maxn*maxn, INF); 60 | for (int i = 0; i < m; ++i) { 61 | scanf("%d %d", &u, &v); 62 | scanf("%d %d", &G[u][v], &cost[u][v]); 63 | G[v][u] = G[u][v]; cost[v][u] = cost[u][v]; 64 | } 65 | Dijkstr(st); 66 | DFS(ed); 67 | printf("%d %d\n", d[ed], c[ed]); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /算法笔记/A1031_Hello World for U.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | string s; cin >> s; 7 | int len = s.length(); 8 | int n1 = (len+2)/3, n2 = (len+2)/3, n3 = (len+2)/3; 9 | n2 += (len+2) % 3; 10 | for (int i = 0; i < n1; ++i) { 11 | if (i != n1-1) { 12 | cout << s[i]; 13 | for (int j = 0; j < n2-2; ++j) cout << ' '; 14 | cout << s[len-1-i] << endl; 15 | } 16 | else { 17 | for (int j = i; j < i + n2; ++j) cout << s[j]; 18 | cout << endl; 19 | } 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /算法笔记/A1032_Sharing.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 用数组下标模拟地址 3 | 建一个next数组 存放下一个字符的地址 数组下标是当前字符的地址 4 | 建一个hashtable 遍历第一个单词 地址被访问过该下标记为1 5 | 遍历第二个单词 遇到被访问过的地址 返回地址 否则 返回-1 6 | ***/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | int main() { 12 | const int maxn = 100010; 13 | int next[maxn] = {0}, hashtable[maxn] = {0}; 14 | int head1, head2, n; scanf("%d %d %d", &head1, &head2, &n); 15 | int now, nxt; char ch; 16 | while (n--) { 17 | scanf("%d %c %d", &now, &ch, &nxt); next[now] = nxt; 18 | } 19 | while (head1 != -1) { 20 | hashtable[head1] = 1; head1 = next[head1]; 21 | } 22 | bool find = false; 23 | while (head2 != -1) { 24 | if (hashtable[head2]) { 25 | find = true; break; 26 | } 27 | head2 = next[head2]; 28 | } 29 | if (find) printf("%05d\n", head2); 30 | else printf("-1\n"); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /算法笔记/A1035_Password.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct stu { 8 | string name, pwd; 9 | }; 10 | 11 | int modif(stu &a) { 12 | bool ismo = false; 13 | for (int i = 0; i < a.pwd.length(); ++i) { 14 | switch (a.pwd[i]) { 15 | case '1': 16 | a.pwd[i] = '@'; 17 | ismo = true; 18 | break; 19 | case '0': 20 | a.pwd[i] = '%'; 21 | ismo = true; 22 | break; 23 | case 'l': 24 | a.pwd[i] = 'L'; 25 | ismo = true; 26 | break; 27 | case 'O': 28 | a.pwd[i] = 'o'; 29 | ismo = true; 30 | break; 31 | default: 32 | break; 33 | } 34 | } 35 | return ismo; 36 | } 37 | 38 | int main() { 39 | int n; cin >> n; 40 | stu students[n]; 41 | vector v; 42 | for (int i = 0; i < n; ++i) { 43 | cin >> students[i].name >> students[i].pwd; 44 | if (modif(students[i])) v.push_back(students[i]); 45 | } 46 | if (v.size()) { 47 | cout << v.size() << endl; 48 | vector::iterator it; 49 | for (it = v.begin(); it != v.end(); ++it) cout << (*it).name << ' ' << (*it).pwd << endl; // .优先级h高于* 50 | } 51 | else { 52 | if (n == 1) cout << "There is 1 account and no account is modified" << endl; 53 | else printf("There are %d accounts and no account is modified\n", n); 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /算法笔记/A1037_Magic Coupon.cpp: -------------------------------------------------------------------------------- 1 | // 思路 让同号最大的两个数相乘 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | bool big2small(long long a, long long b) { 8 | return a > b; 9 | } 10 | 11 | int main() { 12 | int nc, np; 13 | vector cPositive, cNegative, pPositive, pNegative; 14 | long long tmp; 15 | scanf("%d", &nc); 16 | for (int i = 0; i < nc; ++i) { 17 | scanf("%lld", &tmp); 18 | if (tmp >= 0) cPositive.push_back(tmp); 19 | else cNegative.push_back(tmp); 20 | } 21 | scanf("%d", &np); 22 | for (int i = 0; i < np; ++i) { 23 | scanf("%lld", &tmp); 24 | if (tmp >= 0) pPositive.push_back(tmp); 25 | else pNegative.push_back(tmp); 26 | } 27 | sort(cPositive.begin(), cPositive.end(), big2small); 28 | sort(pPositive.begin(), pPositive.end(), big2small); 29 | sort(cNegative.begin(), cNegative.end()); 30 | sort(pNegative.begin(), pNegative.end()); 31 | long long money = 0; 32 | int size1 = cPositive.size(), size2 = pPositive.size(), size3 = cNegative.size(), size4 = pNegative.size(); 33 | for (int i = 0; i < size1 && i < size2; ++i) money += cPositive[i] * pPositive[i]; 34 | for (int i = 0; i < size3 && i < size4; ++i) money += cNegative[i] * pNegative[i]; 35 | printf("%lld\n", money); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /算法笔记/A1038 Recover the Smallest Number.cpp: -------------------------------------------------------------------------------- 1 | // 晴神好聪明啊 一语点醒 原来可以cmp的时候就对拼接后的字符串排序了 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | bool cmp(string a, string b) { 8 | return a+b < b+a; // "32" "321" -> "321" "32" 9 | } 10 | 11 | int main() { 12 | int n; cin >> n; 13 | string arr[10010]; 14 | for (int i = 0; i < n; ++i) cin >> arr[i]; 15 | sort(arr, arr+n, cmp); 16 | string ans = ""; 17 | for (int i = 0; i < n; ++i) ans += arr[i]; 18 | while (ans != "" && ans[0] == '0') ans.erase(0, 1); 19 | if (ans == "") cout << "0" << endl; 20 | else cout << ans << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /算法笔记/A1039_Course List for Student.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 使用map: name-set的数据结构 3 | IO说明: 4 | n-有几个人来查询 k-总共几门课 5 | 接下来k行(index:1~k) 课程编号-i 选课人数-ni 6 | ni个名字 7 | n个要查询的名字 8 | 9 | 对于每个要查询的名字(查询顺序) 输出 名字 选课总数 选的课索引(升序) 10 | ***/ 11 | #include 12 | #include 13 | #include 14 | #include 15 | using namespace std; 16 | 17 | int main() { 18 | int n, k; scanf("%d %d", &n, &k); 19 | map > m; 20 | int tmpi, tmpni; char name[10] = {0}; 21 | for (int i = 0; i < k; ++i) { 22 | scanf("%d %d", &tmpi, &tmpni); 23 | while (tmpni--) { 24 | scanf("%s", name); m[name].insert(tmpi); 25 | } 26 | } 27 | for (int i = 0; i < n; ++i) { 28 | scanf("%s", name); printf("%s %d", name, m[name].size()); 29 | if (m[name].size()) { 30 | set::iterator it = m[name].begin(); 31 | for (; it != m[name].end(); ++it) printf(" %d", *it); 32 | } 33 | printf("\n"); 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /算法笔记/A1040_Longest Symmetric String.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 边界 d[i][i]=1 d[i][i+1] = s[i]==s[i+1] ? 1 : 0 3 | 转移 s[i] == s[j] dp[i+1][j-1] == 1 ? 1 : 0 4 | s[i] != s[j] dp[i][j] = 0 5 | 为确保状态转移后的子串已经被判断 枚举子串长L来状态转移 6 | ***/ 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | int main() { 13 | string s; getline(cin, s); int ans = 1; 14 | int len = s.length(); int dp[1010][1010] = {0}; 15 | for (int i = 0; i < len; ++i) { // 初始化 16 | dp[i][i] = 1; 17 | if (i < len-1) { 18 | if (s[i] == s[i+1]) { 19 | dp[i][i+1] = 1; ans = 2; 20 | } 21 | } 22 | } 23 | for (int l = 3; l <= len; ++l) { 24 | for (int i = 0; i+l-1 < len; ++i) { // 枚举长为l的子串的左右端点 25 | int j = i+l-1; // 右端点 26 | if (s[i] == s[j]) { 27 | if (dp[i+1][j-1]) { 28 | dp[i][j] = 1; ans = l; 29 | } 30 | } 31 | } 32 | } 33 | printf("%d\n", ans); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /算法笔记/A1041_Be Unique.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int arr[100001] = {0}; 6 | int hash[10001] = {0}; 7 | int n; scanf("%d", &n); 8 | for (int i = 0; i < n; ++i) { 9 | scanf("%d", &arr[i]); hash[arr[i]]++; 10 | } 11 | int win = 0; 12 | for (int i = 0; i < n; ++i) { 13 | if (hash[arr[i]] == 1) { 14 | win = arr[i]; break; 15 | } 16 | } 17 | if (win) printf("%d\n", win); 18 | else printf("None\n"); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /算法笔记/A1043_Is It a Binary Search Tree.cpp: -------------------------------------------------------------------------------- 1 | // sequence就是insertion sequence = =? 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct node { 7 | int data; 8 | node* left; 9 | node* right; 10 | }; 11 | 12 | void insert(node*& root, int data) { 13 | if (root == NULL) { 14 | root = new node; root->data = data; 15 | root->left = root->right = NULL; 16 | return; 17 | } 18 | if (data < root->data) insert(root->left, data); 19 | else insert(root->right, data); 20 | } 21 | 22 | void preOrder(node* root, vector& vi) { // 先序遍历的结果存在vi 23 | if (root == NULL) return; 24 | vi.push_back(root->data); 25 | preOrder(root->left, vi); 26 | preOrder(root->right, vi); 27 | } 28 | 29 | void preOrderMirror(node* root, vector& vi) { 30 | if (root == NULL) return; 31 | vi.push_back(root->data); 32 | preOrderMirror(root->right, vi); 33 | preOrderMirror(root->left, vi); 34 | } 35 | 36 | void postOrder(node* root, vector& vi) { 37 | if (root == NULL) return; 38 | postOrder(root->left, vi); 39 | postOrder(root->right, vi); 40 | vi.push_back(root->data); 41 | } 42 | 43 | void postOrderMirror(node* root, vector& vi) { 44 | if (root == NULL) return; 45 | postOrderMirror(root->right, vi); 46 | postOrderMirror(root->left, vi); 47 | vi.push_back(root->data); 48 | } 49 | 50 | vector origin, pre, preM, post, postM; 51 | int main() { 52 | int n, data; scanf("%d", &n); 53 | node* root = NULL; 54 | for (int i = 0; i < n; ++i) { 55 | scanf("%d", &data); 56 | origin.push_back(data); 57 | insert(root, data); 58 | } 59 | preOrder(root, pre); 60 | preOrderMirror(root, preM); 61 | postOrder(root, post); 62 | postOrderMirror(root, postM); 63 | if (origin == pre) { 64 | printf("YES\n"); 65 | for (int i = 0; i < post.size(); ++i) { 66 | if (i) printf(" "); 67 | printf("%d", post[i]); 68 | } 69 | } 70 | else if (origin == preM) { 71 | printf("YES\n"); 72 | for (int i = 0; i < postM.size(); ++i) { 73 | if (i) printf(" "); 74 | printf("%d", postM[i]); 75 | } 76 | } 77 | else printf("NO\n"); 78 | delete []root; 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /算法笔记/A1044_Shopping in Mars .cpp: -------------------------------------------------------------------------------- 1 | // 查找题->二分查找 2 | // 钱的累加是单调递增的->sum[] 3 | // 两个端点i,j之间的钱是sum[j]-sum[i-1] -> 4 | // sum[j]-sum[i-1]=m ->sum[j] = sum[i-1]+m -> 5 | // 枚举左端点i 查找是否存在使该等式恰好成立的右端点j 6 | // 否则 寻找第一个大于sum[i-1]+m的sum[j]->上界 7 | 8 | #include 9 | using namespace std; 10 | 11 | int sum[100010]; 12 | int upper_bound(int l, int r, int x) { 13 | int left = l, right = r, mid; 14 | while(left < right) { 15 | mid = (left + right) / 2; 16 | if (sum[mid] > x) right = mid; 17 | else left = mid + 1; 18 | } 19 | return left; 20 | } 21 | 22 | int main() { 23 | int n, m; scanf("%d %d", &n, &m); 24 | int nearm = 100010001; sum[0] = 0; 25 | for (int i = 1; i <= n; ++i) { 26 | scanf("%d", &sum[i]); sum[i] += sum[i-1]; 27 | } 28 | for (int i = 1; i <= n; ++i) { // 枚举左端点 29 | int j = upper_bound(i, n+1, sum[i-1]+m); // 找到右端点/上界 30 | if (sum[j-1] - sum[i-1] == m) { // 找到了恰好够付的方案 31 | nearm = m; break; 32 | } 33 | else if (j <=n && sum[j]-sum[i-1] < nearm) { // 大于m但更接近m的点 34 | nearm = sum[j]-sum[i-1]; // 更新nearm 35 | } 36 | } 37 | for (int i = 1; i <= n; ++i) { // 列出所有方案 m/nearm 38 | int j = upper_bound(i, n+1, sum[i-1]+nearm); 39 | if (sum[j-1]-sum[i-1] == nearm) printf("%d-%d\n", i, j-1); 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /算法笔记/A1044_Shopping in Mars.cpp: -------------------------------------------------------------------------------- 1 | // 查找题->二分查找 2 | // 钱的累加是单调递增的->sum[] 3 | // 两个端点i,j之间的钱是sum[j]-sum[i-1] -> 4 | // sum[j]-sum[i-1]=m ->sum[j] = sum[i-1]+m -> 5 | // 枚举左端点i 查找是否存在使该等式恰好成立的右端点j 6 | // 否则 寻找第一个大于sum[i-1]+m的sum[j]->上界 7 | 8 | #include 9 | using namespace std; 10 | 11 | int sum[100010]; 12 | int upper_bound(int l, int r, int x) { 13 | int left = l, right = r, mid; 14 | while(left < right) { 15 | mid = (left + right) / 2; 16 | if (sum[mid] > x) right = mid; 17 | else left = mid + 1; 18 | } 19 | return left; 20 | } 21 | 22 | int main() { 23 | int n, m; scanf("%d %d", &n, &m); 24 | int nearm = 100010001; sum[0] = 0; 25 | for (int i = 1; i <= n; ++i) { 26 | scanf("%d", &sum[i]); sum[i] += sum[i-1]; 27 | } 28 | for (int i = 1; i <= n; ++i) { // 枚举左端点 29 | int j = upper_bound(i, n+1, sum[i-1]+m); // 找到右端点/上界 30 | if (sum[j-1] - sum[i-1] == m) { // 找到了恰好够付的方案 31 | nearm = m; break; 32 | } 33 | else if (j <=n && sum[j]-sum[i-1] < nearm) { // 大于m但更接近m的点 34 | nearm = sum[j]-sum[i-1]; // 更新nearm 35 | } 36 | } 37 | for (int i = 1; i <= n; ++i) { // 列出所有方案 m/nearm 38 | int j = upper_bound(i, n+1, sum[i-1]+nearm); 39 | if (sum[j-1]-sum[i-1] == nearm) printf("%d-%d\n", i, j-1); 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /算法笔记/A1045_Favorite Color Stripe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 10010; 6 | int pos[maxn] = {0}, given[maxn] = {0}, dp[maxn] = {0}; 7 | 8 | int main() { 9 | int n, m, color, L, newL = 0; scanf("%d", &n); 10 | scanf("%d", &m); 11 | for (int i = 1; i <= m; ++i) { 12 | scanf("%d", &color); pos[color] = i; // 颜色映射成数字 13 | } 14 | scanf("%d", &L); 15 | for (int i = 0; i < L; ++i) { 16 | scanf("%d", &color); 17 | if (pos[color]) given[newL++] = pos[color]; // 剪掉eva不要的颜色同时映射数字 18 | } 19 | int ans = 0; fill(dp, dp+maxn, 1); // 最优解全部初始化为1 20 | for (int i = 0; i < newL; ++i) { // 遍历裁剪后的给定色块 21 | for (int j = 0; j < i; ++j) { // 遍历i之前的最优解 看是否能产生更优解 22 | if (given[i] >= given[j]) dp[i] = max(dp[j]+1, dp[i]); 23 | } 24 | ans = max(ans, dp[i]); 25 | } 26 | printf("%d\n", ans); 27 | } 28 | -------------------------------------------------------------------------------- /算法笔记/A1047_Student List for Course.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | vector类型的数组 3 | IO说明: 4 | n-学生总数 k-课程总数 5 | 接下来n行: 名字 参加课程总数c c个课程编号 6 | 7 | 输出:课程编号(1~k) 选课学生数 8 | 字典序的名字 一行一个 9 | ***/ 10 | #include 11 | #include 12 | #include 13 | #include 14 | using namespace std; 15 | 16 | int main() { 17 | int n, k; scanf("%d %d", &n, &k); 18 | vector arr[2510]; char name[10] = {0}; int c, index; 19 | for (int i = 0; i < n; ++i) { 20 | scanf("%s %d", name, &c); 21 | while (c--) { 22 | scanf("%d", &index); arr[index].push_back(name); 23 | } 24 | } 25 | for (int i = 1; i <= k; ++i) { 26 | printf("%d %d\n", i, arr[i].size()); 27 | if (arr[i].empty()) continue; 28 | sort(arr[i].begin(), arr[i].end()); 29 | for (int j = 0, len = arr[i].size(); j < len; ++j) printf("%s\n", arr[i][j].c_str()); 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /算法笔记/A1048_Find Coins.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int hashtable[501] = {0}; // 下标对应面额 6 | int n, m; scanf("%d %d", &n, &m); 7 | int tmp; 8 | for (int i = 0; i < n; ++i) { 9 | scanf("%d", &tmp); hashtable[tmp]++; 10 | } 11 | bool find = false; int v1 = 0, v2 = 0; 12 | for (int i = 1; i <= 500 && !find; ++i) { 13 | if (hashtable[i] > 1) { // 处理特殊情况 14 | if (2 * i == m) { 15 | find = true; v1 = v2 = i; break; 16 | } 17 | } 18 | if (hashtable[i]) { // 有这个面额的硬币 19 | for (int j = i+1; j <= 500; ++j) { 20 | if (hashtable[j]) { 21 | if (i + j == m) { 22 | find = true; v1 = i; v2 = j; break; 23 | } 24 | } 25 | } 26 | } 27 | } 28 | if (find) printf("%d %d\n", v1, v2); 29 | else printf("No Solution\n"); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /算法笔记/A1049_Counting Ones.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int n, a = 1, ans = 0; 6 | int left, now, right; 7 | scanf("%d", &n); 8 | while (n / a != 0) { 9 | left = n / (a * 10); 10 | now = n / a % 10; 11 | right = n % a; 12 | if (now == 0) ans += left * a; 13 | else if (now == 1) ans += left * a + right + 1; 14 | else ans += (left + 1) * a; 15 | a *= 10; 16 | } 17 | printf("%d\n", ans); 18 | return 0; 19 | } 20 | 21 | /*** 22 | 样例 23 | 例如n=12,k=1,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],我们发现1出现了5次 (1, 10, 11, 12) 24 | 25 | 思想:按位分析,从个位开始一位位分析,最后计算每个位中K出现次数的和 26 | 27 | 对个位进行分析: 28 | 29 | 例1:n=723, k=1   即((n%10)>k) 30 | 31 | 个位:个位出现1的情况为001,011,021........711,721 32 | 33 | 出现的个数为:73次  即n/10+1 34 | 35 | 例2: n=723,k=3  即((n%10)==k) 36 | 37 | 个位:个位出现3的情况为003,013,023........713,723 38 | 39 | 出现的个数为:73次  即n/10+1 40 | 例3:n=723,k=5  即((n%10)k) 47 | 十位:十位出现1的情况为010~019,110~029.........610~619,710~719 48 | 出现的个数为:80次 即(n/10/10+1)*10 49 | 例2:n=723,k=2 即(((n/10)%10)==k) 50 | 十位:十位出现2的情况为020~029,020~029.........620~629,720~723 51 | 出现的次数是7*10+4=74 即(n/10/10)*10+n%10+1 52 | 例3:n=723,k=3 即(((n/10)%10)k)  singlecount=(p/10+1)*(10^num); 61 | if(p%10==k) singlecount=(p/10)*(10^num)+n%(10^num)+1; 62 | if(p%10 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | string s1, s2; getline(cin, s1); getline(cin, s2); 7 | int hashtable[128] = {0}; 8 | for (int i = 0, len = s2.length(); i < len; ++i) hashtable[s2[i]] = 1; 9 | for (int i = 0, len = s1.length(); i < len; ++i) { 10 | if (hashtable[s1[i]]) continue; 11 | cout << s1[i]; 12 | } 13 | cout << endl; 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /算法笔记/A1051_Pop Sequence.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 建栈模拟 now指向目标序列arr首位 3 | push(num) while(栈不空&&栈顶数字==arr[now]&&now 7 | #include 8 | using namespace std; 9 | 10 | int main() { 11 | int m, n , k; scanf("%d %d %d", &m, &n, &k); 12 | int arr[1010]; 13 | while (k--) { 14 | for (int i = 0; i < n; ++i) scanf("%d", &arr[i]); 15 | int now = 0; stack s; 16 | for (int i = 1; i <= n && now < n && s.size() < m; ++i) { 17 | s.push(i); 18 | while (!s.empty() && s.top() == arr[now] && now < n) { 19 | s.pop(); ++now; 20 | } 21 | } 22 | if (now < n) printf("NO\n"); 23 | else printf("YES\n"); 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /算法笔记/A1052_Linked List Sorting.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 先存储所有node 3 | 从头节点开始遍历 把有效节点push到vector里 4 | 对vector进行排序 输出 5 | ***/ 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | const int maxn = 10001; 12 | struct node { 13 | int address, data, next; 14 | }nodes[100002]; 15 | bool cmp(node a, node b) { 16 | return a.data < b.data; 17 | } 18 | 19 | int main() { 20 | int n, head; scanf("%d %d", &n, &head); 21 | while(n--) { 22 | node tmp; 23 | scanf("%d %d %d", &tmp.address, &tmp.data, &tmp.next); 24 | nodes[tmp.address] = tmp; 25 | } 26 | vector validNodes; node headNode = nodes[head]; 27 | while (headNode.address != -1) { 28 | validNodes.push_back(headNode); 29 | if(headNode.next==-1){ 30 | break; 31 | } 32 | headNode = nodes[headNode.next]; 33 | } 34 | sort(validNodes.begin(), validNodes.end(), cmp); 35 | 36 | if (validNodes.empty()||head==-1) { 37 | printf("0 -1\n"); return 0; 38 | } 39 | printf("%d %05d\n", validNodes.size(), validNodes[0].address); 40 | for (int i = 0, len = validNodes.size(); i < len; ++i) { 41 | printf("%05d %d ", validNodes[i].address, validNodes[i].data); 42 | if (i!= len-1) printf("%05d\n", validNodes[i+1].address); 43 | else printf("-1\n"); 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /算法笔记/A1053_Path of Equal Weight.cpp: -------------------------------------------------------------------------------- 1 | // 普通性质的树 -> 结构体数组模拟 2 | // 最后输出要从大到小 -> 对每个节点的直系子节点合集vector排序 3 | // 优先遍历权值较大的节点 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | const int maxn = 110; 10 | struct node { 11 | int weight; 12 | vector child; // 存放的是子节点的序号 13 | }Node[maxn]; 14 | 15 | bool cmp(int a, int b) { 16 | return Node[a].weight > Node[b].weight; 17 | } 18 | 19 | int n, m, s; 20 | int path[maxn]; // 记录路径 21 | 22 | //index当前访问节点序号 numNode为当前path上节点个数 23 | void DFS(int index, int numNode, int sum) { 24 | if (sum > s) return; 25 | if (sum == s) { 26 | if (Node[index].child.size() != 0) return; // 最后一个不是叶节点 27 | for (int i = 0; i < numNode; ++i) { 28 | if (i) printf(" "); 29 | printf("%d", Node[path[i]].weight); 30 | } 31 | printf("\n"); return; 32 | } 33 | for (int i = 0; i < Node[index].child.size(); ++i) { 34 | int child = Node[index].child[i]; // 节点index的第i个子节点编号 35 | path[numNode] = child; 36 | DFS(child, numNode+1, sum+Node[child].weight); 37 | } 38 | } 39 | 40 | int main() { 41 | scanf("%d %d %d", &n, &m, &s); 42 | for (int i = 0; i < n; ++i) scanf("%d", &Node[i].weight); 43 | int id, k, child; 44 | for (int i = 0; i < m; ++i) { 45 | scanf("%d %d", &id, &k); 46 | for (int j = 0; j < k; ++j) { 47 | scanf("%d", &child); Node[id].child.push_back(child); 48 | } 49 | sort(Node[id].child.begin(), Node[id].child.end(), cmp); 50 | } 51 | path[0] = 0; // 路径的第一个节点为0号节点 52 | DFS(0, 1, Node[0].weight); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /算法笔记/A1054_The Dominant Color .cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 开哈希表会超时 3 | 用map 4 | ***/ 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int main() { 10 | int m, n, tmp; scanf("%d %d", &m, &n); 11 | map mp; 12 | for (int row = 0; row < n; ++row) { 13 | for (int col = 0; col < m; ++ col) { 14 | scanf("%d", &tmp); mp[tmp]++; 15 | } 16 | } 17 | int half = m * n / 2; 18 | map::iterator it = mp.begin(); 19 | for (; it != mp.end(); ++it) { 20 | if (it->second > half) { 21 | printf("%d\n", it->first); break; 22 | } 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /算法笔记/A1055_The World's Richest.cpp: -------------------------------------------------------------------------------- 1 | // 第一次用了一个骚气的vector数组 只过了2/3 第二次改成传统方法就过了。。 2 | // 这个故事告诉我们 先用传统方法 攻破不了再出奇招 3 | // 晴神说 把每个年龄的前100名另存在一个valid数组里取遍历 不然会超时 4 | // 不过经过实践 并没有超时(大雾 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | struct peo { 13 | string name; 14 | int age, wealth; 15 | }; 16 | 17 | bool cmp(peo a, peo b) { 18 | if (a.wealth != b.wealth) return a.wealth > b.wealth; 19 | if (a.age != b.age) return a.age < b.age; 20 | return a.name < b.name; 21 | } 22 | 23 | int main() { 24 | int n, k; scanf("%d %d", &n, &k); 25 | peo people[n]; 26 | for (int i = 0; i < n; ++i) { 27 | char arr[100] = {0}; 28 | scanf("%s %d %d", arr, &people[i].age, &people[i].wealth); 29 | people[i].name = arr; // scanf只能读入字符数组 但string可以直接接收字符数组 30 | } 31 | sort(people, people+n, cmp); 32 | for (int i = 1; i <= k; ++i) { 33 | printf("Case #%d:\n", i); 34 | int m, amin, amax; scanf("%d %d %d", &m, &amin, &amax); 35 | int cnt = 0; 36 | for (int j = 0; j < n; ++j) { 37 | if (cnt == m) break; 38 | if (people[j].age >= amin && people[j].age <= amax) { 39 | printf("%s %d %d\n", people[j].name.c_str(), people[j].age, people[j].wealth); 40 | cnt++; 41 | } 42 | } 43 | if (!cnt) printf("None\n"); 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /算法笔记/A1056_Mice and Rice.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | IO说明: 3 | 选手总数np 一个组的选手数ng 4 | np个老鼠的体重 没有重复体重 (0~np) 5 | np个选手序号 (乱序) 6 | 7 | 输出最后每个选手的名次(按照原序列) 8 | 9 | 思路:用结构体mouse存储选手体重 选手名次 用队列挨个处理 10 | 每次晋级的老鼠数量 = 当前这轮组的数量 11 | 每一轮没有晋级的老鼠排名 = group+1 12 | 比如4个人晋级下一轮 没晋级的这一轮就都是并列第5名 13 | ***/ 14 | 15 | #include 16 | #include 17 | using namespace std; 18 | 19 | const int maxn = 1010; 20 | struct mouse { 21 | int weight, r; 22 | }mice[maxn]; 23 | 24 | int main() { 25 | int np, ng, order; 26 | scanf("%d %d", &np, &ng); 27 | // mice数组是静止的 等着被赋予名次 28 | for (int i = 0; i < np; ++i) scanf("%d", &mice[i].weight); 29 | queue q; 30 | for (int i = 0; i < np; ++i) { // 大家排队比赛 每ng个为一组 31 | scanf("%d", &order); q.push(order); // 编号就相当于指针啦 不用把mice元素搬来搬去 32 | // 通过指针把名次传输给mice元素 33 | } 34 | int nowTotal = np, group; // nowTotal当前这轮的选手总数 group组数 35 | while (q.size() != 1) { // 角逐到只剩一个->第一名 36 | if (nowTotal % ng == 0) group = nowTotal / ng; 37 | else group = nowTotal / ng + 1; 38 | for (int i = 0; i < group; ++i) { // 找出每一组中最重的 39 | int maxID = q.front(); // 最重老鼠的编号 40 | for (int j = 0; j < ng; ++j) { 41 | if (i * ng + j >= nowTotal) break; // 如果最后一组个数不足ng个 提前退出循环 42 | if (mice[q.front()].weight > mice[maxID].weight) maxID = q.front(); 43 | mice[q.front()].r = group + 1; q.pop(); // 顺便赋予每一个选手名次 44 | } 45 | q.push(maxID); 46 | } 47 | nowTotal = group; // group个选手晋级到下一轮 48 | } 49 | mice[q.front()].r = 1; 50 | for (int i = 0; i < np; ++i) { 51 | if (i) printf(" "); 52 | printf("%d", mice[i].r); 53 | } 54 | return 0; 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /算法笔记/A1057_Stack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 100010; 7 | int base = 316; // 每316一块 8 | int table[1010] = {0}; // 记录每块的数字数量 9 | int hashtable[maxn] = {0}; // 记录某数字出现次数 10 | 11 | void peekM(int k) { 12 | int sum = 0, idx = 0; 13 | while (sum + table[idx] < k) sum += table[idx++]; 14 | int num = idx * base; // idx块内第一个数字 15 | while (sum + hashtable[num] < k) sum += hashtable[num++]; 16 | printf("%d\n", num); 17 | } 18 | 19 | int main() { 20 | int n; scanf("%d", &n); 21 | char command[20] = {0}; int key; 22 | stack s; 23 | while (n--) { 24 | scanf("%s", command); 25 | switch (command[1]) { 26 | case 'o': 27 | if (!s.empty()) { 28 | printf("%d\n", s.top()); 29 | hashtable[s.top()]--; table[s.top()/base]--; 30 | s.pop(); 31 | } else printf("Invalid\n"); 32 | break; 33 | case 'u': 34 | scanf("%d", &key); s.push(key); 35 | hashtable[key]++; table[key/base]++; 36 | break; 37 | case 'e': 38 | if (s.empty()) { 39 | printf("Invalid\n"); break; 40 | } 41 | int pos = s.size(); // 中位数位置 42 | if (pos % 2) pos = (pos+1) / 2; 43 | else pos /= 2; 44 | peekM(pos); 45 | break; 46 | } 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /算法笔记/A1058_A+B in Hogwarts.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct money { 6 | int gall, sick, knut; 7 | }; 8 | 9 | int main() { 10 | money m[2]; 11 | for (int i = 0; i < 2; ++i) { 12 | scanf("%d.%d.%d", &m[i].gall, &m[i].sick, &m[i].knut); 13 | } 14 | bool add = false; 15 | if (m[0].knut + m[1].knut >= 29) { 16 | m[1].knut = (m[0].knut + m[1].knut) % 29; 17 | add = true; 18 | } else m[1].knut = m[0].knut + m[1].knut; 19 | int tmp = m[0].sick + m[1].sick; 20 | if (add) { 21 | tmp++; add = false; 22 | } 23 | if (tmp >= 17) { 24 | m[1].sick = tmp % 17; 25 | add = true; 26 | } else m[1].sick = tmp; 27 | m[1].gall = m[0].gall + m[1].gall; 28 | if (add) m[1].gall++; 29 | printf("%d.%d.%d\n", m[1].gall, m[1].sick, m[1].knut); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /算法笔记/A1059_Prime Factors.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 从小到大枚举素数 n除它除到不能除为止 3 | 结构体数组存储质因数和它对应的个数 4 | ***/ 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | struct fac { 10 | long long x, cnt; 11 | }factors[11]; 12 | 13 | bool isPrime(long long n) { 14 | if (n < 2) return false; 15 | long long sqr = (long long)sqrt(1.0 * n); 16 | for (int i = 2; i <= sqr; ++i) { 17 | if (n % i == 0) return false; 18 | } 19 | return true; 20 | } 21 | 22 | int main() { 23 | long long n; scanf("%lld", &n); int facCnt = 0; 24 | if (n == 1) { 25 | printf("1=1\n"); return 0; 26 | } 27 | printf("%lld=", n); 28 | long long sqr = (long long)sqrt(1.0 * n); 29 | for (int i = 2; i <= sqr; ++i) { 30 | if (isPrime(i) && n % i == 0) { 31 | factors[facCnt].x = i; factors[facCnt].cnt = 0; 32 | while (n % i == 0) { 33 | factors[facCnt].cnt++; n /= i; 34 | } 35 | facCnt++; 36 | } 37 | if (n == 1) break; 38 | } 39 | if (n != 1) { 40 | factors[facCnt].x = n; factors[facCnt++].cnt = 1; 41 | } 42 | for (int i = 0; i < facCnt; ++i) { 43 | if (i) printf("*"); 44 | printf("%lld", factors[i].x); 45 | if (factors[i].cnt > 1) printf("^%lld", factors[i].cnt); 46 | } 47 | printf("\n"); 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /算法笔记/A1060_Are They Equal .cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 科学计数法 最后输出的形式时 0.x * 10^x 3 | base和exp都相同时输出YES 否则输出NO 4 | 输入数据小数点前可能会有前导0 erase掉 5 | -> 如果删成了.xxx 指针从小数点往后找第一个非0数字 每移动一位pow-- 6 | -> 如果移到最后都没找到非0 说明这个数字就是0 base=0 pow=0 7 | -> 如果删成了ddd.xxx 指针从小数点往前移到d前面 每移动一位pow++ 8 | ***/ 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | int n; // 有效位数 14 | string deal(string s, int& e) { 15 | int k = 0; // s的下标 16 | while(s.length() > 0 && s[0] == '0') s.erase(0, 1); 17 | if (s[0] == '.') { 18 | s.erase(0, 1); 19 | while (s.length() > 0 && s[0] == '0') { 20 | s.erase(0, 1); e--; 21 | } 22 | } 23 | else { 24 | while (s[k] != '.' && k < s.length()) { 25 | ++k; ++e; 26 | } 27 | if (k < s.length()) s.erase(k, 1); // 碰到了小数点 删除 28 | } 29 | if (s.length() == 0) e = 0; 30 | int num = 0; k = 0; 31 | string res; 32 | while (num < n) { 33 | if (k < s.length()) res += s[k++]; 34 | else res += '0'; 35 | num++; 36 | } 37 | return res; 38 | } 39 | 40 | int main() { 41 | string s1, s2, s3, s4; 42 | cin >> n >> s1 >> s2; 43 | int e1 = 0, e2 = 0; 44 | s3 = deal(s1, e1); s4 = deal(s2, e2); 45 | if (s3 == s4 && e1 == e2) cout << "YES 0." << s3 << "*10^" << e1 << endl; 46 | else cout << "NO 0." << s3 << "*10^" << e1 << " 0." << s4 << "*10^" << e2 << endl; 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /算法笔记/A1061_Dating.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | string code[4]; 9 | for (int i = 0; i < 4; ++i) cin >> code[i]; 10 | string week[] = {"MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"}; 11 | int len1 = code[0].length(); 12 | int len2 = code[1].length(); 13 | int i; 14 | for (i = 0; i < len1 && i < len2; ++i) { 15 | if (code[0][i] == code[1][i] && code[0][i] >= 'A' && code[0][i] <= 'G') { 16 | cout << week[code[0][i]-'A'] << ' '; 17 | break; 18 | } 19 | } 20 | for (i++; i < len1 && i < len2; ++i) { 21 | if (code[0][i] == code[1][i]) { 22 | if (isdigit(code[0][i])) { 23 | printf("%02d:", code[0][i]-'0'); 24 | break; 25 | } 26 | else if (code[0][i] >= 'A' && code[0][i] <= 'N') { 27 | printf("%02d:", code[0][i]-'A'+10); 28 | break; 29 | } 30 | } 31 | } 32 | int len3 = code[2].length(); 33 | int len4 = code[3].length(); 34 | for (i = 0; i < len3 && i < len4; ++i) { 35 | if (code[2][i] == code[3][i]) { 36 | if (isalpha(code[2][i])) { 37 | printf("%02d\n", i); 38 | break; 39 | } 40 | } 41 | } 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /算法笔记/A1062_Talent and Virtu.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct stu { 8 | string id; 9 | int vir, tal, total; 10 | int grade; 11 | }; 12 | 13 | bool cmp(stu a, stu b) { 14 | if (a.grade != b.grade) return a.grade < b.grade; 15 | if (a.total != b.total) return a.total > b.total; 16 | else if (a.vir != b.vir) return a.vir > b.vir; 17 | return a.id < b.id; 18 | } 19 | 20 | int main() { 21 | int n, l, h; cin >> n >> l >> h; 22 | vector students; 23 | stu tmp; 24 | while (n--) { 25 | cin >> tmp.id >> tmp.vir >> tmp.tal; 26 | tmp.total = tmp.vir + tmp.tal; 27 | if (tmp.vir < l || tmp.tal < l) continue; 28 | if (tmp.vir >= h && tmp.tal >= h) tmp.grade = 1; 29 | else if (tmp.vir >= h) tmp.grade = 2; 30 | else if (tmp.vir >= tmp.tal) tmp.grade = 3; // 第一次取了>三个用例没过。。not below >= 31 | else tmp.grade = 4; 32 | students.push_back(tmp); 33 | } 34 | sort(students.begin(), students.end(), cmp); 35 | cout << students.size() << endl; 36 | vector::iterator it = students.begin(); 37 | for (; it != students.end(); ++it) cout << (*it).id << ' ' << (*it).vir << ' ' << (*it).tal << endl; 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /算法笔记/A1063_Set Similarity.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 用stl的合并函数最后一个测试点会超时 这种时候就要踏踏实实遍历 3 | IO说明: 4 | n-集合个数 接下来n行 5 | m-该集合元素个数 m个数字 6 | q-要查询的集合对数 接下来q行 7 | 集合1 集合2 8 | ***/ 9 | 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | const int N = 51; 15 | set st[N]; 16 | 17 | void cmp(int x, int y) { 18 | int totalNum = st[y].size(), sameNum = 0; 19 | for (set::iterator it = st[x].begin(); it != st[x].end(); ++it) { 20 | if (st[y].find(*it) != st[y].end()) sameNum++; 21 | else totalNum++; 22 | } 23 | printf("%.1lf%%\n", sameNum * 100.0 / totalNum); // 先乘再除 比 先除再乘 误差小 24 | } 25 | 26 | int main() { 27 | int n, m, q, v, st1, st2; 28 | scanf("%d", &n); 29 | for (int i = 1; i <= n; ++i) { 30 | scanf("%d", &m); 31 | for (int j = 0; j < m; ++j) { 32 | scanf("%d", &v); st[i].insert(v); 33 | } 34 | } 35 | scanf("%d", &q); 36 | for (int i = 0; i < q; ++i) { 37 | scanf("%d %d", &st1, &st2); 38 | cmp(st1, st2); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /算法笔记/A1064_Complete Binary Search Tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 1010; 6 | int tree[maxn] = {0}; 7 | int numbers[maxn] = {0}; 8 | 9 | int i = 0, n; 10 | void inOrder(int root) { // root的left是2*root right是2*root+1 11 | if (root > n) return; 12 | inOrder(2*root); 13 | tree[root] = numbers[i++]; 14 | inOrder(2*root+1); 15 | } 16 | 17 | int main() { 18 | scanf("%d", &n); 19 | for (int i = 0; i < n; ++i) scanf("%d", &numbers[i]); 20 | sort(numbers, numbers+n); 21 | inOrder(1); // 上面那个公式 需要root从1开始 22 | for (int i = 1; i <= n; ++i) { 23 | printf("%d", tree[i]); 24 | if (i != n) printf(" "); 25 | } 26 | printf("\n"); return 0; 27 | } 28 | -------------------------------------------------------------------------------- /算法笔记/A1067 Sort with Swap(0, i).cpp: -------------------------------------------------------------------------------- 1 | // 目标是 pos[i] = i 即数字i的位置正好是i 2 | // 题目要求交换中介只能是数字0 3 | // 那么当数字0不在位置0上 数字0应该把它所处的位置i还给数字i 即交换pos[0]和pos[pos[0]] 数字i所在位置为pos[pos[0]] 4 | // 当数字0在位置0上 检查剩下的位置是否还有错乱 5 | // 若有 将数字0的位置与找到的第一个错乱的位子交换 借助0的帮助 让正确的数字回到这个错乱的位置上 6 | // 为避免超时 每次搜寻 从最小的错乱位置start开始 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main() { 12 | int n; scanf("%d", &n); 13 | int pos[100010]; int num; 14 | int unsort = 0; 15 | for (int i = 0; i < n; ++i) { 16 | scanf("%d", &num); pos[num] = i; // num在i位置 17 | if (num && num != i) unsort++; 18 | } 19 | int start = 1, cnt = 0; 20 | while (unsort) { 21 | if (pos[0] == 0) { 22 | while (start < n) { 23 | if (pos[start] != start) { 24 | swap(pos[0], pos[start]); cnt++; break; 25 | } 26 | start++; 27 | } 28 | } 29 | while (pos[0] != 0) { 30 | swap(pos[0], pos[pos[0]]); // 将0与pos[0]交换 31 | cnt++; unsort--; 32 | } 33 | } 34 | printf("%d\n", cnt); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /算法笔记/A1069_The Black Hole of Numbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | string s; cin >> s; int not4 = 4 - s.length(); 9 | while (not4--) s = "0"+s; 10 | int big, small, ans = 0; 11 | do { 12 | sort(s.begin(), s.end(), greater()); big = stoi(s); 13 | sort(s.begin(), s.end()); small = stoi(s); 14 | ans = big - small; s = to_string(ans); 15 | not4 = 4 - s.length(); while (not4--) s = "0"+s; 16 | printf("%04d - %04d = %04d\n", big, small, ans); 17 | } while (ans && ans != 6174); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /算法笔记/A1070_Mooncake.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct moon { 6 | double inventory, totalp, price; 7 | }cakes[1010]; 8 | 9 | bool cmp(moon a, moon b) { 10 | return a.price > b.price; 11 | } 12 | 13 | int main() { 14 | int n, d; scanf("%d %d", &n, &d); 15 | for (int i = 0; i < n; ++i) scanf("%lf", &cakes[i].inventory); 16 | for (int i = 0; i < n; ++i) { 17 | scanf("%lf", &cakes[i].totalp); cakes[i].price = cakes[i].totalp / cakes[i].inventory; 18 | } 19 | sort(cakes, cakes+n, cmp); 20 | double wage = 0.0; 21 | for (int i = 0; i < n && d; ++i) { 22 | if (d >= cakes[i].inventory) { 23 | wage += cakes[i].totalp; d -= cakes[i].inventory; 24 | } 25 | else { 26 | wage += cakes[i].price * d; d = 0; 27 | } 28 | } 29 | printf("%.2f\n", wage); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /算法笔记/A1071_Speech Patterns.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 单词之间以非alnum为界限 3 | 词频统计 map 4 | ***/ 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main() { 12 | string s; getline(cin, s); 13 | map m; 14 | int index = 0, len = s.length(); 15 | while (index < len) { 16 | if (!isalnum(s[index])) { 17 | ++index; continue; 18 | } 19 | string word = ""; 20 | while (isalnum(s[index])) word += tolower(s[index++]); 21 | m[word]++; 22 | } 23 | map::iterator it = m.begin(); 24 | string ans = ""; int cnt = 0; 25 | for (; it != m.end(); ++it) { 26 | if (it->second > cnt) { 27 | cnt = it->second; ans = it->first; 28 | } 29 | } 30 | cout << ans << " " << cnt << endl; 31 | return 0; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /算法笔记/A1073_Scientific Notation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | string strnum, base, strexp; cin >> strnum; 8 | int posE = strnum.find('E'); 9 | strexp = strnum.substr(posE+1, strnum.length()-1-posE); 10 | int exp = stoi(strexp); 11 | base = strnum.substr(1, posE-1); 12 | if (exp == 0) { 13 | cout << base << endl; return 0; 14 | } 15 | if (strnum[0] == '-') cout << '-'; 16 | base.erase(1,1); // 去除小数点 17 | strnum = base; 18 | 19 | if (exp >= 0) { 20 | if (exp > base.length() - 1) { // 如果右移到base长度后面 补零 21 | for (int i = 0; i < exp-(base.length()-1); ++i) strnum += '0'; 22 | } 23 | else if (exp < base.length() - 1) strnum.insert(1+exp, "."); // 否则 在原小数点位(1)后exp个位置插入小数点 24 | } 25 | else { 26 | exp = 0 - exp; 27 | for (int i = 0; i < exp - 1; ++i) { // 补exp-1个0 28 | strnum = "0" + strnum; 29 | } 30 | strnum = "0." + strnum; 31 | } 32 | // 去除头部多余的0 不除0就会出现00.12这种错误 小数点前最多一个0 非零数字前不能有0 33 | // PAT这道题不需要这个操作 因为限定了 [+-][1-9].[0-9]+E[+-][0-9]+ 34 | // if (strnum.find('.') != string::npos) { 35 | // int posdot = strnum.find('.')-1; 36 | // for (int i = 0; i < posdot; ++i) { 37 | // if (strnum[i] == '0') strnum.erase(i, 1); 38 | // else break; 39 | // } 40 | // } 41 | // else { 42 | // for (int i = 0; i < strnum.length(); ++i) { 43 | // if (strnum[i] == '0') strnum.erase(i, 1); 44 | // else break; 45 | // } 46 | // } 47 | cout << strnum << endl; 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /算法笔记/A1074_Reversing Linked List .cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 建立结构体node 存储本身地址 data next地址 3 | 建立vector validNodes 4 | 晴神的思路 把vector分为n/k块 每块反转输出 每个节点的next等于它前一个的地址 5 | 每块末尾节点的next等于前一块末尾的地址preEnd 6 | ***/ 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | const int maxn = 100010; 13 | struct node { 14 | int address, data, next; 15 | }nodes[maxn]; 16 | 17 | int main() { 18 | int head, n, k; scanf("%d %d %d", &head, &n, &k); 19 | node tmp; 20 | for (int i = 0; i < n; ++i) { 21 | scanf("%d %d %d", &tmp.address, &tmp.data, &tmp.next); 22 | nodes[tmp.address] = tmp; 23 | } 24 | bool end = false; 25 | bool begin = true; 26 | int i =0; 27 | while (!end) { 28 | stack s; vector v; 29 | while (s.size() < k) { 30 | s.push(nodes[head]); v.push_back(nodes[head]); 31 | if (nodes[head].next == -1) { 32 | end = true; break; // 已经是最后一个节点 33 | } 34 | head = nodes[head].next; 35 | } 36 | if (s.size() == k) { 37 | while (!s.empty()) { 38 | node now = s.top(); 39 | if(!begin) printf("%05d\n", now.address); 40 | printf("%05d %d ", now.address, now.data); 41 | s.pop(); 42 | if(!s.empty()){ 43 | node next = s.top(); 44 | printf("%05d\n", next.address); 45 | begin = true; 46 | }else{ 47 | if (i+1==n) printf("-1\n"); 48 | begin = false; 49 | } 50 | i++; 51 | } 52 | } 53 | else { 54 | for (int j = 0, len = v.size(); j < len; ++j) { 55 | if(!begin) printf("%05d\n", v[j].address); 56 | printf("%05d %d ", v[j].address, v[j].data); 57 | if (v[j].next == -1) printf("-1\n"); 58 | else printf("%05d\n", v[j+1].address); 59 | begin = true; 60 | } 61 | } 62 | 63 | } 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /算法笔记/A1076_Forwards on Weibo.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 涉及到层数 -> BFS 3 | 1000的量级 -> 邻接矩阵 4 | node从1开始编号 5 | only L levels of indirect followers are counted -> 发出者的layer设为0 6 | 7 | 题意就是求顶点u在L层内的子节点个数 8 | ***/ 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | const int maxn = 1010; int n, l; 14 | int G[maxn][maxn] = {0}; 15 | bool vis[maxn] = {false}; 16 | 17 | int BFS(int u) { 18 | int cnt = 0; 19 | queue Q; 20 | bool inq[maxn] = {false}; int L[maxn] = {0}; // 记录每个节点的layer 21 | Q.push(u); inq[u] = true; 22 | while (!Q.empty()) { 23 | int fro = Q.front(); Q.pop(); 24 | for (int i = 1; i <= n; ++i) { // 枚举所有节点 25 | if (G[fro][i] && !inq[i]) { // fro可以直接到达i 26 | L[i] = L[fro] + 1; 27 | if (L[i] > l) return cnt; 28 | Q.push(i); inq[i] = true; cnt++; 29 | } 30 | } 31 | } 32 | return cnt; 33 | } 34 | 35 | int main() { 36 | scanf("%d %d", &n, &l); 37 | int k, idol; 38 | for (int usr = 1; usr <= n; ++usr) { 39 | scanf("%d", &k); 40 | while (k--) { 41 | scanf("%d", &idol); G[idol][usr] = 1; 42 | } 43 | } 44 | int qNum, q; scanf("%d", &qNum); 45 | while (qNum--) { 46 | scanf("%d", &q); 47 | printf("%d\n", BFS(q)); 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /算法笔记/A1077_Kuchiguse.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | string lcs(string text, string aim) { // 寻找最长公共后缀 8 | if (text == "" || aim == "") return ""; 9 | int len1 = text.length(), len2 = aim.length(); 10 | string kuchi = ""; 11 | int minlen = len1 < len2 ? len1 : len2; 12 | reverse(text.begin(), text.end()); // 反转以后就可以从前往后做比较 比较方便 13 | reverse(aim.begin(), aim.end()); 14 | for (int i = 0; i < minlen; ++i) { 15 | if (text[i] == aim[i]) kuchi += aim[i]; 16 | else break; 17 | } 18 | reverse(kuchi.begin(), kuchi.end()); 19 | return kuchi; 20 | } 21 | 22 | int main() { 23 | int n; cin >> n; 24 | getchar(); // 把n后面的换行符吃掉 25 | string tmp1; getline(cin, tmp1); n--; 26 | while (n--) { 27 | string tmp2; getline(cin, tmp2); 28 | tmp1 = lcs(tmp2, tmp1); 29 | } 30 | if (tmp1[0] == ' ') tmp1.erase(0); // kuchi字符串第一位可能是空格 31 | if (tmp1 != "") cout << tmp1 << endl; 32 | else cout << "nai" << endl; 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /算法笔记/A1078_Hashing.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 数字key的index = key % TSize 3 | msize如果不是质数 把它变成离它最近的质数 4 | 如果index > msize或者index位已经被占用 输出 “-” 否则 输出index 5 | ***/ 6 | 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | bool isPrime(int n) { 12 | if (n < 2) return false; 13 | int sqr = int(sqrt(1.0 * n)); 14 | for (int i = 2; i <= sqr; ++i) { 15 | if (n % i == 0) return false; 16 | } 17 | return true; 18 | } 19 | 20 | int main() { 21 | int msize, n, tmp; scanf("%d %d", &msize, &n); 22 | while (!isPrime(msize)) msize++; 23 | int hashtable[10010] = {0}; 24 | for (int i = 0; i < n; ++i) { 25 | scanf("%d", &tmp); int index = tmp % msize; 26 | if (i) printf(" "); 27 | if (!hashtable[index]) { 28 | printf("%d", index); hashtable[index] = 1; 29 | } 30 | else { // 处理冲突 31 | int step = 1, cpyIndex = index; bool find = false; 32 | while (step < msize) { // / 正向二次方探查 如果step在msize里找不到 比它大的更找不到 33 | cpyIndex = (index + step * step) % msize; 34 | if (!hashtable[cpyIndex]) { 35 | printf("%d", cpyIndex); hashtable[cpyIndex] = 1; find = true; break; 36 | } 37 | step++; 38 | } 39 | if (!find) printf("-"); 40 | } 41 | } 42 | printf("\n"); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /算法笔记/A1079_Total Sales of Supply Chain.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 1.00 - r% -> r是0.01 3 | 商品售出价格为 root的价格*1.01^(卖的人所在层数) 4 | 到达了叶子节点才算卖出去 并计入总销售额 5 | ***/ 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | 13 | const int maxn = 100010; 14 | struct node { 15 | vector child; 16 | double amount; 17 | }nodes[maxn]; 18 | 19 | double p, r, ans = 0.0; 20 | void DFS(int index, int depth) { // index-正在访问的节点编号 depth层数 21 | if (nodes[index].child.empty()) { // 没有孩子->到达叶子节点 22 | ans += p * pow(1+r, depth) * nodes[index].amount; return; 23 | } 24 | for (int i = 0, len = nodes[index].child.size(); i < len; ++i) { 25 | DFS(nodes[index].child[i], depth+1); 26 | } 27 | 28 | } 29 | 30 | int main() { 31 | int n; scanf("%d %lf %lf", &n, &p, &r); 32 | r /= 100; int k, tmp; // 孩子数量 孩子序号 33 | for (int i = 0; i < n; ++i) { 34 | scanf("%d", &k); 35 | for (int j = 0; j < k; ++j){ 36 | scanf("%d", &tmp); nodes[i].child.push_back(tmp); 37 | } 38 | if (k == 0) { 39 | scanf("%lf", &nodes[i].amount); 40 | } 41 | } 42 | DFS(0, 0); 43 | printf("%.1f\n", ans); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /算法笔记/A1080_Graduate Admission.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct stu { 7 | int id; 8 | double g1, g2, g3; 9 | int choice[5]; 10 | }; 11 | 12 | bool cmp(stu a, stu b) { 13 | if (a.g3 != b.g3) return a.g3 > b.g3; 14 | return a.g1 > b.g1; 15 | } 16 | bool cmpId(stu a, stu b) { 17 | return a.id < b.id; 18 | } 19 | 20 | int main() { 21 | int n, m, k; scanf("%d %d %d", &n, &m, &k); 22 | int schoolsLimit[100]; vector inschool[100]; 23 | vector students; stu tmp; 24 | for (int i = 0; i < m; ++i) scanf("%d", &schoolsLimit[i]); 25 | for (int i = 0; i < n; ++i) { 26 | tmp.id = i; 27 | scanf("%lf %lf", &tmp.g1, &tmp.g2); 28 | tmp.g3 = (tmp.g1 + tmp.g2) / 2; 29 | for (int j = 0; j < k; ++j) scanf("%d", &tmp.choice[j]); 30 | students.push_back(tmp); 31 | } 32 | 33 | sort(students.begin(), students.end(), cmp); // rank靠前的先安排 34 | for (int i = 0; i < n; ++i) { 35 | // printf("%d\n", students[i].id); 36 | for (int j = 0; j < k; ++j) { 37 | int want = students[i].choice[j]; 38 | if (inschool[want].size() < schoolsLimit[want]) { // 想去的学校还有名额 39 | inschool[want].push_back(students[i]); break; 40 | } 41 | else { 42 | if (inschool[want].back().g3 == students[i].g3 && inschool[want].back().g1 == students[i].g1) { // 没名额了 但是该考生和该校录取的最后一名高考总分相同 43 | inschool[want].push_back(students[i]); break; 44 | } 45 | } 46 | } 47 | } 48 | for (int i = 0; i < m; ++i) { 49 | if (inschool[i].size() == 0) printf("\n"); 50 | else { 51 | sort(inschool[i].begin(), inschool[i].end(), cmpId); 52 | for (int j = 0; j < inschool[i].size(); ++j) { 53 | if (j) printf(" "); 54 | printf("%d", inschool[i][j].id); 55 | } 56 | printf("\n"); 57 | } 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /算法笔记/A1081_Rational Sum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct fract { 6 | long long up, down; 7 | }; 8 | fract ans, tmp; 9 | 10 | long long abs(long long n) { 11 | if (n < 0) return -n; 12 | else return n; 13 | } 14 | 15 | long long gcd(long long a, long long b) { 16 | return !b ? a : gcd(b, a % b); 17 | } 18 | 19 | void simplify() { 20 | if (ans.down < 0) { // 保证负号一定在分子前面 21 | ans.up = -ans.up; ans.down = - ans.down; 22 | } 23 | if (ans.up == 0) ans.down = 1; 24 | else { 25 | long long d = gcd(abs(ans.up), ans.down); 26 | ans.up /= d; ans.down /= d; 27 | } 28 | } 29 | 30 | void add() { 31 | ans.up = ans.up * tmp.down + tmp.up * ans.down; 32 | ans.down *= tmp.down; 33 | simplify(); 34 | } 35 | 36 | int main() { 37 | int n; scanf("%d", &n); ans.up = 0; ans.down = 1; 38 | for (int i = 0; i < n; ++i) { 39 | scanf("%lld/%lld", &tmp.up, &tmp.down); 40 | add(); 41 | } 42 | if (ans.down == 1) printf("%lld\n", ans.up); 43 | else if (ans.up > ans.down) { 44 | printf("%lld %lld/%lld\n", abs(ans.up) / ans.down, abs(ans.up) % ans.down, ans.down); 45 | } 46 | else printf("%lld/%lld\n", ans.up, ans.down); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /算法笔记/A1082_Read Number in Chinese.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | s.erase(pos) 删除字符串s从第pos个字符开始之后所有的字符(包括第pos个) 3 | s.erase(pos,n) 删除字符串s从第pos个字符开始的n个字符 4 | ***/ 5 | 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int main() { 12 | string unit[] = {"", "Shi", "Bai", "Qian"}; // 用len索引 13 | string secs[] = {"", "Wan", "Yi"}; // secs是加在unit后面的 个位节 万节 亿节 用seccnt索引 14 | string number[] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"}; 15 | 16 | string n; cin >> n; 17 | if (n == "0") { 18 | cout << "ling" << endl; 19 | return 0; 20 | } 21 | string ans = ""; 22 | if (n[0] == '-') { 23 | cout << "Fu "; n.erase(0, 1); 24 | } 25 | int seccnt = 0; 26 | int end = n.length()-1; 27 | for (; end >= 0; end -= 4) { // 四位为一段 end是sec的末端 28 | bool after0 = false; 29 | int start = end >= 3 ? end - 3 : 0; // start是sec的开端 30 | int len = end - start + 1 - 1; // 这个sec的长度 闭区间所以+1 为了索引所以-1 31 | string tmp = ""; // 该sec的读法 32 | for (int i = start; i <= end; ++i) { 33 | if (n[i] == '0') { 34 | len--; 35 | after0 = true; 36 | } 37 | else { 38 | if (after0) { // 只有被夹在两个非0数中间的0才被发音 39 | tmp += " ling"; 40 | after0 = false; 41 | } 42 | if (tmp.length() != 0) tmp += " "; // 如果不是第一次插入tmp 要加空格 43 | tmp += number[n[i]-'0']; 44 | if (len > 0) tmp += ' '; //非个位的unit要输出 和数字间有空格 45 | tmp += unit[len--]; 46 | } 47 | } 48 | if (seccnt > 0) tmp += " "; tmp += secs[seccnt++]; // 如果不是个位节 都要输出sec单位 49 | if (start != 0 && tmp[0] != ' ') tmp = " " + tmp; // 如果该段是" ling"开头就不需要拼接空格了 50 | ans = tmp + ans; // 因为是从后往前 所以tmp要接在ans前面 51 | } 52 | cout << ans << endl; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /算法笔记/A1083_List Grades.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct stu { 8 | string name, id; 9 | int grade; 10 | }; 11 | 12 | bool cmp(stu a, stu b) { 13 | return a.grade < b.grade; 14 | } 15 | 16 | int main() { 17 | int n; cin >> n; 18 | vector students; 19 | stu tmp; 20 | for (int i = 0; i < n; ++i) { 21 | cin >> tmp.name >> tmp.id >> tmp.grade; 22 | students.push_back(tmp); 23 | } 24 | int grade1, grade2; cin >> grade1 >> grade2; 25 | sort(students.begin(), students.end(), cmp); 26 | bool find = false; 27 | for (int i = n-1; i >= 0; --i) { 28 | if (students[i].grade < grade1) break; 29 | if (students[i].grade >= grade1 && students[i].grade <= grade2) { 30 | cout << students[i].name << ' ' << students[i].id << endl; 31 | find = true; 32 | } 33 | } 34 | if (!find) cout << "NONE" << endl; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /算法笔记/A1084_Broken Keyboard.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | int hashtable[128] = {0}; // 下标为字符ascii码 128h够用 值0-没记录过 值1-记录过了 9 | string s1, s2; cin >> s1 >> s2; 10 | int i = 0, j = 0; 11 | int len1 = s1.length(), len2 = s2.length(); 12 | for (; i < len1; ++i) { 13 | s1[i] = toupper(s1[i]); 14 | if (s1[i] != toupper(s2[j])) { 15 | if (!hashtable[s1[i]]) { 16 | cout << s1[i]; hashtable[s1[i]] = 1; 17 | } 18 | } else ++j; 19 | } 20 | cout << endl; 21 | return 0; 22 | } 23 | 24 | 25 | /*** 26 | 本来想用unordered_set来做的 结果人家是真·乱序而不是保留插入位置= =。 27 | 还发现一个坑 toupper只能暂时转化大写 返回其大写字母的ascii码 ch = toupper(ch) 才行 28 | 把字符转换成大写字母,非字母字符不做出处理 29 | Anyway 字符hash的初体验~ 30 | ***/ 31 | -------------------------------------------------------------------------------- /算法笔记/A1085 Perfect Sequenc_upper_bound().cpp: -------------------------------------------------------------------------------- 1 | // 二分查找法 使用upper_bound函数 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 100010; 7 | int n, p, a[maxn]; // a为升序 8 | 9 | int main() { 10 | scanf("%d %d", &n, &p); 11 | for (int i = 0; i < n; ++i) scanf("%d", &a[i]); 12 | sort(a, a+n); 13 | int ans = 1; // 最大长度 至少有一个数 14 | for (int i = 0; i < n; ++i) { 15 | int end = upper_bound(a+i+1, a+n, (long long)a[i] * p) - a; // 上限为这个东西 16 | ans = max(ans, end - i); 17 | } 18 | printf("%d\n", ans); 19 | return 0; 20 | } 21 | 22 | 23 | //// 二分查找法 (暴力枚举复杂度为n^2 会超时) 24 | //// 排序后从左到右扫描数列 对于每一个a[i] 寻找从a[i+1]到a[n-1]中第一个超过a[i]*p的数字的位置end 25 | //// 这样 end-i就是对位置i而言满足a[j] <= a[i]*p的最远长度 26 | //// 取所有end-i的最大值即为所求 复杂度为logn 27 | //#include 28 | //#include 29 | //#include 30 | //using namespace std; 31 | // 32 | //const int maxn = 100010; 33 | //int n, p, a[maxn]; // a为升序 34 | // 35 | //int binarySearch(int i, long long x) { // 在[i+1, n-1]中寻找第一个大于x的数的位置 36 | // if (a[n-1] <= x) return n; // 如果所有数都不大于x 37 | // int left = i+1, right = n-1, mid; 38 | // while (left < right) { // 注意是<不是<= 因为x不需要真的存在于队列中 ==的时候就是把x该在的位置返回 39 | // mid = (left + (right-left)/2); 40 | // if (a[mid] > x) right = mid; // mid处符合条件 说明第一个符合条件在mid处或者mid的左边 41 | // else left = mid+1; 42 | // } 43 | // return left; // while结束的时候left==right 44 | //} 45 | // 46 | //int main() { 47 | // scanf("%d %d", &n, &p); 48 | // for (int i = 0; i < n; ++i) scanf("%d", &a[i]); 49 | // sort(a, a+n); 50 | // int ans = 1; // 最大长度 至少有一个数 51 | // for (int i = 0; i < n; ++i) { 52 | // int end = binarySearch(i, (long long)a[i] * p); // 第一个大于x的数字的位置 53 | // ans = max(ans, end - i); 54 | // } 55 | // printf("%d\n", ans); 56 | // return 0; 57 | //} 58 | -------------------------------------------------------------------------------- /算法笔记/A1085 Perfect Sequence_BinarySearch.cpp: -------------------------------------------------------------------------------- 1 | // 二分查找法 (暴力枚举复杂度为n^2 会超时) 2 | // 排序后从左到右扫描数列 对于每一个a[i] 寻找从a[i+1]到a[n-1]中第一个超过a[i]*p的数字的位置end 3 | // 这样 end-i就是对位置i而言满足a[j] <= a[i]*p的最远长度 4 | // 取所有end-i的最大值即为所求 复杂度为logn 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | const int maxn = 100010; 11 | int n, p, a[maxn]; // a为升序 12 | 13 | int binarySearch(int i, long long x) { // 在[i+1, n-1]中寻找第一个大于x的数的位置 14 | if (a[n-1] <= x) return n; // 如果所有数都不大于x 15 | int left = i+1, right = n-1, mid; 16 | while (left < right) { // 注意是<不是<= 因为x不需要真的存在于队列中 ==的时候就是把x该在的位置返回 17 | mid = (left + (right-left)/2); 18 | if (a[mid] > x) right = mid; // mid处符合条件 说明第一个符合条件在mid处或者mid的左边 19 | else left = mid+1; 20 | } 21 | return left; // while结束的时候left==right 22 | } 23 | 24 | int main() { 25 | scanf("%d %d", &n, &p); 26 | for (int i = 0; i < n; ++i) scanf("%d", &a[i]); 27 | sort(a, a+n); 28 | int ans = 1; // 最大长度 至少有一个数 29 | for (int i = 0; i < n; ++i) { 30 | int end = binarySearch(i, (long long)a[i] * p); // 第一个大于x的数字的位置 31 | ans = max(ans, end - i); 32 | } 33 | printf("%d\n", ans); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /算法笔记/A1085_Perfect Sequence_two_pointers.cpp: -------------------------------------------------------------------------------- 1 | // two pointer解法 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int n, p; scanf("%d %d", &n, &p); 8 | long long arr[100010]; 9 | for (int i = 0; i < n; ++i) scanf("%lld", &arr[i]); 10 | sort(arr, arr+n); 11 | int i = 0, j = 0, cnt = 1; 12 | while (i < n && j < n) { 13 | while (j < n && arr[i] * p >= arr[j]) { 14 | cnt = max(j-i+1, cnt); j++; 15 | } 16 | i++; 17 | } 18 | printf("%d\n", cnt); 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /算法笔记/A1086_Tree Traversals Again.cpp: -------------------------------------------------------------------------------- 1 | // push的顺序就是先序遍历的顺序 pop的顺序就是中序遍历的顺序 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | int n; 10 | vector pre, in, post; 11 | 12 | struct node { 13 | int data; 14 | node* left; 15 | node* right; 16 | node() { 17 | left = NULL; right = NULL; 18 | } 19 | }; 20 | 21 | node* createTree(int preL, int preR, int inL, int inR) { 22 | if (preL > preR) return NULL; 23 | node* root = new node; 24 | root->data = pre[preL]; 25 | int k = 0; 26 | for (; k < n; ++k) { 27 | if (in[k] == root->data) break; 28 | } 29 | int numLeft = k - inL; 30 | root->left = createTree(preL+1, preL+numLeft, inL, k-1); 31 | root->right = createTree(preL+numLeft+1, preR, k+1, inR); 32 | return root; 33 | } 34 | 35 | void postOrder(node* root) { 36 | if (root == NULL) return; 37 | postOrder(root->left); 38 | postOrder(root->right); 39 | post.push_back(root->data); 40 | } 41 | 42 | int main() { 43 | cin >> n; 44 | string action; int data; 45 | stack tmp; 46 | while (cin >> action) { 47 | if (action == "Push") { 48 | cin >> data; tmp.push(data); pre.push_back(data); 49 | } 50 | else { 51 | in.push_back(tmp.top()); tmp.pop(); 52 | } 53 | } 54 | node* root = createTree(0, n-1, 0, n-1); 55 | postOrder(root); 56 | for (int i = 0; i < post.size(); ++i) { 57 | if (i) printf(" "); 58 | printf("%d", post[i]); 59 | } printf("\n"); 60 | delete []root; 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /算法笔记/A1088_Rational Arithmetic.cpp: -------------------------------------------------------------------------------- 1 | // 水题 格式调了半天O_o? 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct fraction { 7 | long long up, down; 8 | }; 9 | fraction a, b; 10 | 11 | void rightNegative(fraction& f) { 12 | if (f.down < 0) { 13 | f.up = -f.up; f.down = -f.down; 14 | } 15 | } 16 | 17 | long long gcd(long long a, long long b) { 18 | return !b ? a : gcd(b, a % b); 19 | } 20 | 21 | fraction simplify(fraction ans) { 22 | long long g = gcd(abs(ans.up), ans.down); 23 | ans.up /= g; ans.down /= g; 24 | return ans; 25 | } 26 | 27 | fraction add(fraction a, fraction b) { 28 | fraction ans; 29 | ans.up = a.up * b.down + b.up * a.down; ans.down = a.down * b.down; 30 | return simplify(ans); 31 | } 32 | 33 | fraction minus(fraction a, fraction b) { 34 | b.up = -b.up; return add(a, b); 35 | } 36 | 37 | fraction mul(fraction a, fraction b) { 38 | fraction ans; 39 | ans.up = a.up * b.up; ans.down = a.down * b.down; 40 | return simplify(ans); 41 | } 42 | 43 | fraction div(fraction a, fraction b) { 44 | swap(b.up, b.down); return mul(a, b); 45 | } 46 | 47 | void printFraction(fraction ans) { 48 | ans = simplify(ans); rightNegative(ans); 49 | if (ans.up < 0) printf("(-"); 50 | if (ans.up == 0) printf("0"); 51 | else if (ans.down == 1) printf("%lld", abs(ans.up)); 52 | else if (abs(ans.up) > ans.down) printf("%lld %lld/%lld", abs(ans.up)/ans.down, abs(ans.up)%ans.down, ans.down); 53 | else printf("%lld/%lld", abs(ans.up), ans.down); 54 | if (ans.up < 0) printf(")"); 55 | } 56 | 57 | int main() { 58 | scanf("%lld/%lld %lld/%lld", &a.up, &a.down, &b.up, &b.down); 59 | rightNegative(a); rightNegative(b); 60 | printFraction(a); printf(" + "); printFraction(b); printf(" = "); printFraction(add(a, b)); printf("\n"); 61 | printFraction(a); printf(" - "); printFraction(b); printf(" = "); printFraction(minus(a, b)); printf("\n"); 62 | printFraction(a); printf(" * "); printFraction(b); printf(" = "); printFraction(mul(a, b)); printf("\n"); 63 | printFraction(a); printf(" / "); printFraction(b); printf(" = "); 64 | if (b.up == 0) printf("Inf\n"); 65 | else { 66 | printFraction(div(a, b)); printf("\n"); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /算法笔记/A1089_Insert or Merge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 110; 6 | int origin[maxn], cpyOri[maxn], changed[maxn]; 7 | int n; 8 | 9 | bool isSame(int a[], int b[]) { 10 | for (int i = 0; i < n; ++i) { 11 | if (a[i] != b[i]) return false; 12 | } 13 | return true; 14 | } 15 | 16 | void printArray(int a[]) { 17 | for (int i = 0; i < n; ++i) { 18 | if (i) printf(" "); 19 | printf("%d", a[i]); 20 | } 21 | printf("\n"); 22 | } 23 | 24 | bool insertSort() { 25 | bool flag = false; 26 | for (int i = 1; i < n; ++i) { // 插入排序 第一位左边为空 不需要操作 所以i从1开始 27 | if (i != 1 && isSame(cpyOri, changed)) flag = true; // 不是初始序列且相同 28 | int tmp = cpyOri[i], j = i; // 用tmp暂存主元(要插入的元素)的值 j从右往左使主元左侧有序 29 | while (j >= 1 && cpyOri[j-1] > tmp) { //把大于主元的数往右挪 30 | cpyOri[j] = cpyOri[j-1]; --j; 31 | } 32 | cpyOri[j] = tmp; // 找到了插入位置 插入主元的值 33 | if (flag) return true; // 在这里返回 同时完成了目标序列的下一轮排序 34 | } 35 | return false; 36 | } 37 | 38 | void mergeSort() { 39 | bool flag = false; 40 | for (int step = 2; step / 2 <= n; step *= 2) { 41 | if (step != 2 && isSame(cpyOri, changed)) flag = true; 42 | for (int i = 0; i < n; i += step) sort(cpyOri+i, cpyOri+min(i+step, n)); //一组一组地排序 43 | if (flag) return; 44 | } 45 | } 46 | 47 | int main() { 48 | scanf("%d", &n); 49 | for (int i = 0; i < n; ++i) { 50 | scanf("%d", &origin[i]); cpyOri[i] = origin[i]; 51 | } 52 | for (int i = 0; i < n; ++i) scanf("%d", &changed[i]); 53 | if (insertSort()) { 54 | printf("Insertion Sort\n"); printArray(cpyOri); 55 | } 56 | else { 57 | printf("Merge Sort\n"); 58 | for (int i = 0; i < n; ++i) cpyOri[i] = origin[i]; 59 | mergeSort(); printArray(cpyOri); 60 | } 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /算法笔记/A1090_Highest Price in Supply Chain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 100010; 7 | vector nodes[maxn]; 8 | int n; double p, r; 9 | 10 | double maxDepth = -1; int num = 0; 11 | void DFS(int index, int depth) { 12 | if (nodes[index].empty()) { 13 | if (depth > maxDepth) { 14 | maxDepth = depth; num = 1; 15 | } 16 | else if (depth == maxDepth) num++; 17 | return; 18 | } 19 | for (int i = 0; i < nodes[index].size(); ++i) { 20 | DFS(nodes[index][i], depth+1); 21 | } 22 | } 23 | 24 | int main() { 25 | scanf("%d %lf %lf", &n, &p, &r); 26 | r /= 100; 27 | int sup, root; 28 | for (int i = 0; i < n; ++i) { 29 | scanf("%d", &sup); 30 | if (sup != -1) nodes[sup].push_back(i); 31 | else root = i; 32 | } 33 | DFS(root, 0); 34 | printf("%.2f %d\n", p*pow(1+r, maxDepth), num); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /算法笔记/A1091_Acute Stroke.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | IO说明: 3 | 输入 M行 N列 L层 T阈值 4 | 接下来有L个 m*n的矩阵 5 | 6 | 输出core总数 7 | 一个core块 只有相邻(上下左右前后)的1的总数>=T时才被加入total 8 | 9 | 思路:块状广搜 标记式 10 | ***/ 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | struct node { 16 | int x, y, z; 17 | }Node; 18 | 19 | int m, n, slice, T; 20 | int pixel[1300][150][70]; 21 | bool inq[1300][150][70] = {false}; 22 | int X[6] = {1, -1, 0, 0, 0, 0}; 23 | int Y[6] = {0, 0, 1, -1, 0, 0}; 24 | int Z[6] = {0, 0, 0, 0, 1, -1}; 25 | 26 | bool judge(int x, int y, int z) { 27 | if (x >= m || x < 0 || y >= n || y < 0 || z >= slice || z < 0) return false; // 越界 28 | if (!pixel[x][y][z] || inq[x][y][z]) return false; // 节点不是所求值或者已经入队 29 | return true; 30 | } 31 | 32 | int BFS(int x, int y, int z) { 33 | int cores = 0; Node.x = x; Node.y = y; Node.z = z; 34 | queue Q; Q.push(Node); inq[x][y][z] = true; 35 | while (!Q.empty()) { 36 | node fro = Q.front(); Q.pop(); cores++; 37 | for (int i = 0; i < 6; ++i) { 38 | int newX = X[i] + fro.x, newY = Y[i] + fro.y, newZ = Z[i] + fro.z; 39 | if (judge(newX, newY, newZ)) { 40 | Node.x = newX; Node.y = newY; Node.z = newZ; 41 | Q.push(Node); inq[newX][newY][newZ] = true; 42 | } 43 | } 44 | } 45 | if (cores >= T) return cores; 46 | else return 0; 47 | } 48 | 49 | int main() { 50 | scanf("%d %d %d %d", &m, &n, &slice, &T); 51 | int ans = 0; 52 | for (int z = 0; z < slice; ++z) { 53 | for (int x = 0; x < m; ++x) { 54 | for (int y = 0; y < n; ++y) scanf("%d", &pixel[x][y][z]); 55 | } 56 | } 57 | for (int z = 0; z < slice; ++z) { 58 | for (int x = 0; x < m; ++x) { 59 | for (int y = 0; y < n; ++y) { 60 | if(pixel[x][y][z] && !inq[x][y][z]) ans += BFS(x, y, z); 61 | } 62 | } 63 | } 64 | printf("%d\n", ans); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /算法笔记/A1092_To Buy or Not to Buy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int owner[128] = {0}; 8 | bool enough = true; 9 | int miss = 0, extra = 0; 10 | string s1, s2; cin >> s1 >> s2; 11 | for (int i = 0; i < s1.length(); ++i) owner[s1[i]]++; 12 | for (int i = 0; i < s2.length(); ++i) { 13 | owner[s2[i]]--; 14 | if (owner[s2[i]] < 0) { 15 | enough = false; miss++; 16 | } 17 | } 18 | if (!enough) printf("No %d\n", miss); 19 | else { 20 | for (int i = 0; i < 128; ++i) extra += owner[i]; 21 | printf("Yes %d\n", extra); 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /算法笔记/A1093_Count PAT's.cpp: -------------------------------------------------------------------------------- 1 | // PAT的个数等于=(A左边P的个数)*(A右边T的个数)* A的个数 2 | // 为了更高效 这里的乘采用累加的方法 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | const int maxn= 100010; long long div = 1000000007; 9 | int leftP[maxn] = {0}, rightTNum = 0, ans = 0; 10 | string s; cin >> s; int len = s.length(); 11 | for (int i = 0; i < len; ++i) { 12 | if (i) leftP[i] = leftP[i-1]; 13 | if (s[i] == 'P') leftP[i]++; 14 | } 15 | for (int i = len; i >= 0; --i) { 16 | if (s[i] == 'T') rightTNum++; 17 | else if (s[i] == 'A') ans = (ans + leftP[i]*rightTNum) % div; 18 | } 19 | printf("%d\n", ans); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /算法笔记/A1094_The Largest Generation.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int maxn = 110; int n, m; 6 | vector children[maxn]; 7 | int hashtable[maxn]; 8 | bool isChild[maxn] = {false}; 9 | 10 | void DFS(int index, int depth) { 11 | hashtable[depth]++; 12 | for (int i = 0; i < children[index].size(); ++i) { 13 | DFS(children[index][i], depth+1); 14 | } 15 | } 16 | 17 | int main() { 18 | scanf("%d %d", &n, &m); 19 | int father, k, son; 20 | for (int i = 0; i < m; ++i) { 21 | scanf("%d %d", &father, &k); 22 | while (k--) { 23 | scanf("%d", &son); children[father].push_back(son); 24 | isChild[son] = true; 25 | } 26 | } 27 | DFS(1, 1); 28 | int maxDepth = -1, maxPeople = 0; 29 | for (int i = 1; i < maxn; ++i) { 30 | if (hashtable[i] > maxPeople) { 31 | maxPeople = hashtable[i]; maxDepth = i; 32 | } 33 | } 34 | printf("%d %d\n", maxPeople, maxDepth); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /算法笔记/A1095_Cars on Campus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | struct car { 10 | char id[8]; 11 | int time; 12 | char status[4]; 13 | }all[10010], valid[10010]; 14 | 15 | int timetoint(int hh, int mm, int ss) { 16 | return hh * 3600 + mm * 60 + ss; 17 | } 18 | 19 | bool cmpByIdAndTime(car a, car b) { 20 | if (strcmp(a.id, b.id)) return strcmp(a.id, b.id) < 0; 21 | return a.time < b.time; 22 | } 23 | 24 | bool cmpByTime(car a, car b) { 25 | return a.time < b.time; 26 | } 27 | 28 | int main() { 29 | int n, k, hh, mm, ss; 30 | map parktime; // car->staytime 31 | scanf("%d %d", &n, &k); 32 | for (int i = 0; i < n; ++i) { 33 | scanf("%s %d:%d:%d %s", all[i].id, &hh, &mm, &ss, all[i].status); 34 | all[i].time = timetoint(hh, mm, ss); 35 | } 36 | sort(all, all+n, cmpByIdAndTime); 37 | int maxtime = -1; int validnum = 0; 38 | for (int i = 0; i < n-1; ++i) { 39 | if (!strcmp(all[i].id, all[i+1].id) && 40 | !strcmp(all[i].status, "in") && 41 | !strcmp(all[i+1].status, "out")) { 42 | valid[validnum++] = all[i]; valid[validnum++] = all[i+1]; 43 | int intime = all[i+1].time - all[i].time; 44 | parktime[all[i].id] += intime; 45 | maxtime = max(maxtime, parktime[all[i].id]); 46 | } 47 | } 48 | sort(valid, valid+validnum, cmpByTime); 49 | int now = 0, numcar = 0; 50 | for (int i = 0; i < k; ++i) { 51 | scanf("%d:%d:%d", &hh, &mm, &ss); 52 | int time = timetoint(hh, mm, ss); 53 | while (now < validnum && valid[now].time <= time) { 54 | if (!strcmp(valid[now].status, "in")) numcar++; 55 | else numcar--; 56 | now++; 57 | } 58 | printf("%d\n", numcar); 59 | } 60 | map::iterator it; 61 | for (it = parktime.begin(); it != parktime.end(); ++it) { 62 | if (it->second == maxtime) printf("%s ", it->first.c_str()); 63 | } 64 | printf("%02d:%02d:%02d\n", maxtime/3600, maxtime % 3600 / 60, maxtime % 60); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /算法笔记/A1096_Consecutive Factors.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 从1~sqr遍历数字 寻找最长的一组连续数字 都能被n整除 3 | 当i~j长度>maxLen的时候 更新 start= i maxLen = j-i 4 | ***/ 5 | 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int main() { 11 | long long n; scanf("%lld", &n); 12 | long long sqr = (long long)(sqrt(1.0 * n)); 13 | long long start = 0, maxLen = 0; 14 | for (long long i = 2; i <= sqr; ++i) { 15 | long long tmp = 1, j = i; 16 | while (true) { 17 | tmp *= j; 18 | if (n % tmp) break; 19 | if (j - i + 1 > maxLen) { 20 | start = i; maxLen = j - i + 1; 21 | } 22 | ++j; 23 | } 24 | } 25 | if (maxLen == 0) printf("1\n%lld", n); 26 | else { 27 | printf("%lld\n", maxLen); 28 | for (long long i = 0; i < maxLen; ++i) { 29 | if (i) printf("*"); 30 | printf("%lld", start+i); 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /算法笔记/A1097_Deduplication on a Linked List.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 目前所有做错的链表题,都是因为没有更新next的地址QAQ 3 | 调整后的链表 node的next就等于它下一个节点的address! 4 | 5 | 建立nodes结构体数组 6 | 开个一万大小的hashtable 访问过的值标记为1 7 | 建两个node型的vector uv v 8 | 遍历有效节点时 遇到访问过的值 push到v 否则push到uv 9 | ***/ 10 | #include 11 | #include 12 | #include 13 | using namespace std; 14 | 15 | const int maxn = 100010; 16 | int hashtable[maxn] = {0}; 17 | struct node { 18 | int address, data, next; 19 | }nodes[maxn]; 20 | 21 | int main() { 22 | int head, n; scanf("%d %d", &head, &n); 23 | node tmp; 24 | while (n--) { 25 | scanf("%d %d %d", &tmp.address, &tmp.data, &tmp.next); 26 | nodes[tmp.address] = tmp; 27 | } 28 | node headNode = nodes[head]; bool end = false; 29 | vector uv, v; 30 | while (!end) { 31 | if (hashtable[abs(headNode.data)]) v.push_back(headNode); 32 | else { 33 | uv.push_back(headNode); hashtable[abs(headNode.data)] = 1; 34 | } 35 | if (headNode.next == -1) break; 36 | headNode = nodes[headNode.next]; 37 | } 38 | for (int i = 0, len = uv.size(); i < len; ++i) { 39 | printf("%05d %d ", uv[i].address, uv[i].data); 40 | if (i == len-1) printf("-1\n"); 41 | else printf("%05d\n", uv[i+1].address); 42 | } 43 | for (int i = 0, len = v.size(); i < len; ++i) { 44 | printf("%05d %d ", v[i].address, v[i].data); 45 | if (i == len-1) printf("-1\n"); 46 | else printf("%05d\n", v[i+1].address); 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /算法笔记/A1098_Insertion or Heap Sort .cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 先插入排序 比较是否相等 3 | 否则 就是堆排序 4 | ***/ 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | const int maxn = 110; int n; 10 | int origin[maxn], mid[maxn]; // 存储原序列和中间序列 11 | 12 | bool cmpArr(int a[], int b[]) { 13 | for (int i = 1; i <= n; ++i) { 14 | if (a[i] != b[i]) return false; 15 | } 16 | return true; 17 | } 18 | 19 | void printArr(int arr[]) { 20 | for (int i = 1; i <= n; ++i) { 21 | if (i != 1) printf(" "); 22 | printf("%d", arr[i]); 23 | } 24 | printf("\n"); 25 | } 26 | 27 | bool isInsert() { 28 | for (int i = 3; i <= n+1; ++i) { // 初始序列不算中间序列 29 | sort(origin+1, origin+i); // 02测试点没过是因为sort函数没从1而是0开始排列 30 | if (cmpArr(origin, mid)) { 31 | if (i <= n) sort(origin, origin+i+1); 32 | return true; 33 | } 34 | } 35 | return false; 36 | } 37 | 38 | void downAdjust(int low, int high) { 39 | int i = low, j = 2 * i; // i为欲调整节点 j是i孩子中较大者 初始为左孩子 40 | while (j <= high) { // 当有左孩子 41 | if (j+1 <= high && mid[j+1] > mid[j]) { // 如果有右孩子且比左孩子大 42 | j = j+1; 43 | } 44 | if (mid[j] > mid[i]) { 45 | swap(mid[j], mid[i]); i = j; j = i * 2;// 保持i为欲调整节点 46 | } 47 | else break; // 调整结束 48 | } 49 | } 50 | 51 | void heapSort() { 52 | int k = 2; 53 | while (mid[1] > mid[k]) ++k; 54 | swap(mid[1], mid[--k]); 55 | downAdjust(1, k-1); // 相当于是删除堆顶的操作 56 | printArr(mid); 57 | } 58 | 59 | int main() { 60 | scanf("%d", &n); 61 | for (int i = 1; i <= n; ++i) scanf("%d", &origin[i]);; 62 | for (int i = 1; i <= n; ++i) scanf("%d", &mid[i]); 63 | if (isInsert()) { 64 | printf("Insertion Sort\n"); 65 | printArr(origin); 66 | } 67 | else { 68 | printf("Heap Sort\n"); 69 | heapSort(); 70 | } 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /算法笔记/A1099_Build A Binary Search Tree.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 思路: 3 | 结构体数组表示树 4 | 把从小到大排好序的序列插入中序访问的树节点 5 | 层序遍历输出树 6 | ***/ 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | const int maxn = 110; int n; 13 | int numbers[maxn]; 14 | 15 | struct node { 16 | int data, left, right; 17 | }nodes[maxn]; 18 | 19 | int i = 0; // numbers的索引 20 | void inOrder(int root) { 21 | if (root == -1) return; 22 | inOrder(nodes[root].left); 23 | nodes[root].data = numbers[i++]; 24 | inOrder(nodes[root].right); 25 | } 26 | 27 | int num = 0; // 记录已经输出的节点数 28 | void layerOrder(int root) { 29 | queue Q; Q.push(root); 30 | while (!Q.empty()) { 31 | int fro = Q.front(); Q.pop(); 32 | printf("%d", nodes[fro].data); num++; 33 | if (num < n) printf(" "); 34 | else printf("\n"); 35 | if (nodes[fro].left != -1) Q.push(nodes[fro].left); 36 | if (nodes[fro].right != -1) Q.push(nodes[fro].right); 37 | } 38 | } 39 | 40 | int main() { 41 | scanf("%d", &n); int l, r; 42 | for (int i = 0; i < n; ++i) { 43 | scanf("%d %d", &l, &r); 44 | nodes[i].left = l; nodes[i].right = r; 45 | } 46 | for (int i = 0; i < n; ++i) scanf("%d", &numbers[i]); 47 | sort(numbers, numbers+n); 48 | inOrder(0); 49 | layerOrder(0); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /算法笔记/A1100_Mars Numbers.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 地球数字转火星数字:a*13^1 + b -> hDigit[a] + digit[b] 3 | 火星数字转地球数字:str1 str2 -> str1对应的索引*13^1 + str对应的索引 4 | ***/ 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | string digit[] = {"tret", "jan", "feb", "mar", "apr", "may", "jun", 11 | "jly", "aug", "sep", "oct", "nov", "dec",}; 12 | string hDigit[] = {"", "tam", "hel", "maa", "huh", "tou", "kes", 13 | "hei", "elo", "syy", "lok", "mer", "jou"}; 14 | 15 | string total[] = {"tret", "jan", "feb", "mar", "apr", "may", "jun", 16 | "jly", "aug", "sep", "oct", "nov", "dec", "", "tam", "hel", "maa", "huh", "tou", "kes", 17 | "hei", "elo", "syy", "lok", "mer", "jou"}; 18 | 19 | string earth2Mars(int n) { 20 | if (!n) return "tret"; 21 | string ans = ""; bool add = false; 22 | if (n >= 13) { 23 | ans += hDigit[n/13]; n %= 13; add = true; 24 | } 25 | if (n) { 26 | if (add) ans += " "; 27 | ans += digit[n]; 28 | } 29 | return ans; 30 | } 31 | 32 | int mars2Earth(string n) { 33 | int ans = 0; 34 | if (n.length() > 4) { // 如果有两部分 长度一定会大于4 35 | string s = n.substr(0, n.find(" ")); 36 | for (int i = 1; i <= 12; ++i) { 37 | if (hDigit[i] == s) { 38 | ans += 13 * i; break; 39 | } 40 | } 41 | n.erase(0, n.find(" ")+1); 42 | } 43 | for (int i = 0; i <= 25; ++i) { 44 | if (total[i] == n) { 45 | if (i <= 12) ans += i; 46 | else ans += (i-13) * 13; 47 | } 48 | } 49 | return ans; 50 | } 51 | 52 | int main() { 53 | int N; cin >> N; string tmp; 54 | getchar(); // 吸收换行符 55 | while (N--) { 56 | getline(cin, tmp); 57 | if (isdigit(tmp[0])) cout << earth2Mars(stoi(tmp)) << endl; 58 | else cout << mars2Earth(tmp) << endl; 59 | } 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /算法笔记/A1101_Quick Sort .cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | int n; scanf("%d", &n); 8 | const int maxn = 100010, INF = (1<<31)-1; int arr[maxn]; 9 | int leftMax[maxn], rightMin[maxn]; leftMax[0] = -1; rightMin[n-1] = INF; 10 | for (int i = 0; i < n; ++i) scanf("%d", &arr[i]); 11 | for (int i = 1; i < n; ++i) leftMax[i] = max(leftMax[i-1], arr[i-1]); 12 | for (int i = n - 2; i >= 0; --i) rightMin[i] = min(rightMin[i+1], arr[i+1]); 13 | int ans[maxn]; int cnt = 0; 14 | for (int i = 0; i < n; ++i) { 15 | if (arr[i] >= leftMax[i] && arr[i] <= rightMin[i]) ans[cnt++] = arr[i]; 16 | } 17 | printf("%d\n", cnt); 18 | sort(ans, ans+cnt); 19 | for (int i = 0; i < cnt; ++i) { 20 | if (i) printf(" "); 21 | printf("%d", ans[i]); 22 | } 23 | printf("\n"); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /算法笔记/A1102_Invert a Binary Tree.cpp: -------------------------------------------------------------------------------- 1 | // 因为题目给出的是节点的编号 所以用静态链表 2 | // 先找到根节点 然后顺藤摸瓜 3 | // 输出树反转过来的层序遍历和后序遍历 4 | // 树反转套路: 后序遍历 访问时交换左右节点 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | struct node { 11 | int left, right; 12 | node() { 13 | left = -1; right = -1; 14 | } 15 | }nodes[11]; 16 | 17 | void postOrder(int root) { 18 | if (root == -1) return; 19 | postOrder(nodes[root].left); 20 | postOrder(nodes[root].right); 21 | swap(nodes[root].left, nodes[root].right); 22 | } 23 | 24 | int num1 = 0, n; // 记录已经输出了几个节点 25 | void layerOrder(int root) { 26 | if (root == -1) return; 27 | queue Q; Q.push(root); 28 | while (!Q.empty()) { 29 | int fro = Q.front(); Q.pop(); 30 | printf("%d", fro); num1++; 31 | if (num1 < n) printf(" "); 32 | else printf("\n"); 33 | if (nodes[fro].left != -1) Q.push(nodes[fro].left); 34 | if (nodes[fro].right != -1) Q.push(nodes[fro].right); 35 | } 36 | } 37 | 38 | int num2 = 0; 39 | void inOrder(int root) { 40 | if (root == -1) return; 41 | inOrder(nodes[root].left); 42 | printf("%d", root); num2++; 43 | if (num2 < n) printf(" "); 44 | else printf("\n"); 45 | inOrder(nodes[root].right); 46 | } 47 | 48 | int main() { 49 | scanf("%d", &n); 50 | bool isChild[11] = {false}; char l, r; 51 | for (int i = 0; i < n; ++i) { 52 | scanf(" %c %c", &l, &r); // 最前面的空格吸收换行符 53 | if (l == '-') nodes[i].left = -1; 54 | else { 55 | nodes[i].left = l - '0'; isChild[nodes[i].left] = true; 56 | } 57 | if (r == '-') nodes[i].right = -1; 58 | else { 59 | nodes[i].right = r - '0'; isChild[nodes[i].right] = true; 60 | } 61 | } 62 | int root = -1; 63 | for (int i = 0; i < n; ++i) { 64 | if (!isChild[i]) { 65 | root = i; break; 66 | } 67 | } 68 | postOrder(root); 69 | layerOrder(root); 70 | inOrder(root); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /算法笔记/A1103_Integer Factorization.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int n, k, p, maxFacSum = -1; // 记录最大底数之和 7 | vector fac; // 存放0^p 1^p 2^p...i^p i^p<=n 8 | vector ans, tmp; // 存放最优底数序列和递归中的临时序列 9 | 10 | int pow(int x) { // 计算x的p次方 11 | int ans = 1; 12 | for (int i = 0; i < p; ++i) ans *= x; 13 | return ans; 14 | } 15 | 16 | void init() { 17 | int i = 0, tmp = 0; 18 | while (tmp <= n) { // i^p不超过n时 不断把i^p加入fac 19 | fac.push_back(tmp); tmp = pow(++i); 20 | } 21 | } 22 | 23 | // 当前访问fac[index] nowK当前选中个数 sum序列当前数字之和 facSum当前底数之和 24 | void DFS(int index, int nowK, int sum, int facSum) { 25 | if (sum == n && nowK == k) { // 找到一个满足的序列 26 | if (facSum > maxFacSum) { // 底数之和更优 27 | maxFacSum = facSum; ans = tmp; // 更新最优解 28 | } return; 29 | } 30 | if (sum > n || nowK > k) return; // 非法情况 直接返回 31 | if (index >= 1) { // index从1开始 32 | tmp.push_back(index); // 把底数index加入临时序列tmp 33 | DFS(index, nowK+1, sum+fac[index], facSum+index); // 选第index个数的分支 34 | tmp.pop_back(); // 选的分支结束后把刚加进去的数字pop掉 35 | DFS(index-1, nowK, sum, facSum); // 不选的分支 36 | } 37 | } 38 | 39 | int main() { 40 | scanf("%d %d %d", &n, &k, &p); 41 | init(); 42 | DFS(fac.size()-1, 0, 0, 0); // 从fac的最后一位开始往前搜索 43 | if (maxFacSum == -1) printf("Impossible\n"); 44 | else { 45 | printf("%d = %d^%d", n, ans[0], p); 46 | for (int i = 1; i < ans.size(); ++i) printf(" + %d^%d", ans[i], p); 47 | } 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /算法笔记/A1104_Sum of Number Segments.cpp: -------------------------------------------------------------------------------- 1 | // 每个数会出现(n - i) * (i + 1)次 i是数字的序号 从0开始 2 | // 虽然是找规律题 可以这样理解 3 | // 一个序列中的第i个数字 它后面(算上它自己)有n-i个数字 所以在以它开头的子序列中它会被算n-i次 子序列为{n}的情况在这里被囊括 4 | // 同时 它前面的数字 有一个的话 以它开头的子序列中就可以拼接到后面 它又会被算一轮 -> 前面的数字有k个 组合数=(k+1)(n-i) 5 | // 所以 它被加的总次数 = (前面的数字个数+1)* (后面的数字即n-i) 6 | 7 | #include 8 | 9 | using namespace std; 10 | 11 | int main(){ 12 | int n; 13 | scanf("%d", &n); 14 | double tmp = 0; 15 | double sum = 0; 16 | for(int i = 0; i < n; ++i){ 17 | scanf("%lf", &tmp); 18 | sum += (tmp * (n - i) * (i + 1)); 19 | } 20 | printf("%.2f\n", sum); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /算法笔记/A1105_Spiral Matrix.cpp: -------------------------------------------------------------------------------- 1 | // 超时了两个测试点emmm回头再优化 2 | // 将一个序列降序排列 填入一个顺时针螺旋矩阵 3 | // 穷尽四个方向 直到遇到死胡同或已经访问过 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | const int maxn = 10010; int n; 10 | int arr[maxn] = {0}, ans[maxn][maxn] = {0}; 11 | int row, col; 12 | bool vis[maxn][maxn] = {false}; 13 | int C[4] = {1, 0, -1, 0}; 14 | int R[4] = {0, 1, 0, -1}; // 右下左上四个走法对行列的影响 15 | 16 | bool cmp(int a, int b) { 17 | return a > b; 18 | } 19 | 20 | bool judge(int r, int c, int cnt) { // 判断是否到死胡同 21 | if (r >= row || r < 0 || c >= col || c < 0 || vis[r][c]) return false; 22 | if (cnt > n) return false; 23 | return true; 24 | } 25 | 26 | int main() { 27 | scanf("%d", &n); 28 | for (int i = 0; i < n; ++i) scanf("%d", &arr[i]); 29 | sort(arr, arr+n, cmp); 30 | row = col = int(sqrt(n)); 31 | if (row * col < n) row = n / col; 32 | ans[0][0] = arr[0]; vis[0][0] = true; // 初始化起点 33 | int cnt = 1, r = 0, c = 0; 34 | while (cnt < n) { 35 | while (judge(r+R[0], c+C[0], cnt)) { 36 | r += R[0]; c += C[0]; ans[r][c] = arr[cnt++]; 37 | vis[r][c] = true; 38 | } 39 | while (judge(r+R[1], c+C[1], cnt)) { 40 | r += R[1]; c += C[1]; ans[r][c] = arr[cnt++]; 41 | vis[r][c] = true; 42 | } 43 | while (judge(r+R[2], c+C[2], cnt)) { 44 | r += R[2]; c += C[2]; ans[r][c] = arr[cnt++]; 45 | vis[r][c] = true; 46 | } 47 | while (judge(r+R[3], c+C[3], cnt)) { 48 | r += R[3]; c += C[3]; ans[r][c] = arr[cnt++]; 49 | vis[r][c] = true; 50 | } 51 | } 52 | for (int i = 0; i < row; ++i) { 53 | for (int j = 0; j < col; ++j) { 54 | if (j) printf(" "); 55 | printf("%d", ans[i][j]); 56 | } 57 | printf("\n"); 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /算法笔记/A1106_Lowest Price in Supply Chain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 100010; 7 | vector children[maxn]; 8 | 9 | int lowestDepth = maxn, num = 0; 10 | void DFS(int index, int depth) { 11 | if (children[index].empty()) { 12 | if (depth < lowestDepth) { 13 | lowestDepth = depth; num = 1; 14 | } 15 | else if (depth == lowestDepth) num++; 16 | return; 17 | } 18 | for (int i = 0; i < children[index].size(); ++i) { 19 | DFS(children[index][i], depth+1); 20 | } 21 | } 22 | 23 | int main() { 24 | int n; double p, r; scanf("%d %lf %lf", &n, &p, &r); 25 | r /= 100; 26 | int k, child; 27 | for (int i = 0; i < n; ++i) { 28 | scanf("%d", &k); 29 | for (int j = 0; j < k; ++j) { 30 | scanf("%d", &child); children[i].push_back(child); 31 | } 32 | } 33 | DFS(0, 0); 34 | printf("%.4f %d\n", p*pow(1+r, lowestDepth), num); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /算法笔记/A1107_Social Clusters.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 两个人爱好里只要有一个相同 就合并到一个集合里 3 | ***/ 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | const int maxn = 1010; 9 | int hobbies[maxn] = {0}; // 下标为爱好编号 值为喜欢的人的编号 10 | int father[maxn] = {0}; 11 | int isRoot[maxn] = {0}; // 下标为根节点序号 值为集合中的人 12 | 13 | void init(int n) { 14 | for (int i = 1; i <= n; ++i) father[i] = i; 15 | } 16 | 17 | int findFather(int x) { 18 | int a = x; 19 | while (father[x] != x) x = father[x]; 20 | while (father[a] != a) { // 路径压缩 21 | int b = a; 22 | a = father[a]; 23 | father[b] = x; // 不能一步到位把father[a]改成x 不然还怎么用father[a]更新啊!! 24 | } 25 | return x; 26 | } 27 | 28 | void unionFather(int a, int b) { 29 | int faA = findFather(a); 30 | int faB = findFather(b); 31 | if(faA != faB) father[faA] = faB; 32 | } 33 | 34 | bool cmp(int a, int b){ 35 | return a > b; 36 | } 37 | 38 | int main() { 39 | int n, k, hobby; scanf("%d", &n); 40 | init(n); 41 | for (int i = 1; i <= n; ++i) { // 人的编号为i 42 | scanf("%d: ", &k); 43 | for (int j = 0; j < k; ++j) { // 一共k个爱好 44 | scanf("%d", &hobby); 45 | if (!hobbies[hobby]) hobbies[hobby] = i; // 如果该爱好还没人选过 46 | unionFather(findFather(hobbies[hobby]), i); // 否则 和之前选这个爱好的人的合集合并 47 | } 48 | } 49 | for (int i = 1; i <= n; ++i) { 50 | isRoot[findFather(i)]++; 51 | } 52 | int setNum = 0; 53 | for (int i = 1; i <= n; ++i) { 54 | if (isRoot[i]) setNum++; // 莫装逼~!老实遍历!! 55 | } 56 | printf("%d\n", setNum); 57 | sort(isRoot+1, isRoot+1+n, cmp); 58 | for (int i = 1; i <= setNum; ++i) { 59 | if (i != 1) printf(" "); 60 | printf("%d", isRoot[i]); 61 | } 62 | printf("\n"); 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /算法笔记/B1027_打印沙漏.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | 两个坑 没有remain的时候也要输出0 字符右边不打印空格 3 | **/ 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | int n; 9 | char ch; 10 | cin >> n >> ch; 11 | 12 | int i = 1; 13 | while (n >= 2*i*i-1) { // 用等差数列公示算出n最多支撑几行对称沙漏 14 | ++i; 15 | } 16 | --i; // n有剩余但不足以输出多一行时也进入了循环体 所以-1 17 | int line = 2 * i - 1; // 最长一行长度 18 | int remain = n - (2*i*i-1); 19 | for (int j = i; j >= 2; --j) { 20 | int thisline = 2 * j - 1; 21 | int space1 = (line - thisline) / 2; 22 | while (space1--) cout << ' '; 23 | for (int k = 0; k < thisline; ++k) cout << ch; 24 | cout << endl; 25 | } 26 | int space1 = (line-1) / 2; 27 | while (space1--) cout << ' '; 28 | cout << ch << endl; 29 | for (int j = 2; j <= i; ++j) { 30 | int thisline = 2 * j -1; 31 | int space1 = (line - thisline) / 2; 32 | while (space1--) cout << ' '; 33 | for (int k = 0; k < 2*j-1; ++k) cout << ch; 34 | cout << endl; 35 | } 36 | cout << remain << endl; 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /算法笔记/B1037_在霍格沃茨找零钱.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct money { 6 | int gall, sick, knut; 7 | }; 8 | 9 | bool isbigger(money a, money b) { 10 | if (a.gall != b.gall) return a.gall > b.gall; 11 | if (a.sick != b. sick ) return a.sick > b.sick; 12 | return a.knut > b.knut; 13 | } 14 | 15 | int main() { 16 | money m[3]; 17 | for (int i = 0; i < 2; ++i) scanf("%d.%d.%d", &m[i].gall, &m[i].sick, &m[i].knut); 18 | bool add = false; 19 | if (isbigger(m[0], m[1])) { 20 | money tmp = m[0]; 21 | m[0] = m[1]; 22 | m[1] = tmp; 23 | add = true; 24 | } 25 | if (m[1].knut >= m[0].knut) m[2].knut = m[1].knut - m[0].knut; 26 | else { 27 | m[1].sick--; 28 | m[2].knut = m[1].knut + 29 - m[0].knut; 29 | } 30 | if (m[1].sick >= m[0].sick) m[2].sick = m[1].sick - m[0].sick; 31 | else { 32 | m[1].gall--; 33 | m[2].sick = m[1].sick + 17 - m[0].sick; 34 | } 35 | m[2].gall = m[1].gall - m[0].gall; 36 | if (add) cout << '-'; 37 | cout << m[2].gall << '.' << m[2].sick << '.' << m[2].knut << endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /算法笔记/B1038_统计同成绩学生.cpp: -------------------------------------------------------------------------------- 1 | //#include // 用这个会超时= =。 2 | #include 3 | using namespace std; 4 | 5 | int main() { 6 | int score[101] = {0}; 7 | int n; scanf("%d", &n); 8 | for (int i = 0; i < n; ++i) { 9 | int tmp; scanf("%d", &tmp); score[tmp]++; 10 | } 11 | int k; scanf("%d", &k); 12 | for (int i = 0; i < k; ++i) { 13 | int tmp; scanf("%d", &tmp); 14 | if (i) printf(" "); 15 | printf("%d", score[tmp]); 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /算法笔记/B1042_字符统计.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | string s; getline(cin, s); 8 | int hash[129] = {0}; 9 | for (int i = 0, len = s.length(); i < len; ++i) hash[tolower(s[i])]++; 10 | int max = -1; char maxch = 'a'; 11 | for (int i = 97; i <= 122; ++i) { 12 | if (hash[i] > max) { 13 | max = hash[i]; maxch = i; 14 | } 15 | } 16 | cout << maxch << ' ' << max << endl; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /算法笔记/B1043_输出PATest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int sum(int arr[], int n) { 6 | int ans = 0; 7 | for (int i = 0; i < n; ++i) ans += arr[i]; 8 | return ans; 9 | } 10 | 11 | int main() { 12 | string s; cin >> s; 13 | int hash[6] = {0}; // 对应PATest 14 | string meta = "PATest"; 15 | for (int i = 0, len = s.length(); i < len; ++i) { 16 | if (meta.find(s[i]) != string::npos) hash[meta.find(s[i])]++; 17 | } 18 | while (sum(hash, 6)) { 19 | for (int i = 0; i < 6; ++i) { 20 | if (hash[i]) { 21 | cout << meta[i]; hash[i]--; 22 | } 23 | } 24 | } 25 | cout << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /算法笔记/B1047_编程团体赛.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int hash[1001] = {0}; 6 | int n; scanf("%d", &n); 7 | while (n--) { 8 | int num, eat, grade; scanf("%d-%d %d", &num, &eat, &grade); 9 | hash[num] += grade; 10 | } 11 | int max = -1, maxindex = 0; 12 | for (int i = 1; i < 1001; ++i) { 13 | if (hash[i] > max) { 14 | max = hash[i]; maxindex = i; 15 | } 16 | } 17 | printf("%d %d", maxindex, max); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /算法笔记/B1048_数字加密.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 这道题不严谨,b比a短要在左边补零才能通过,题目啥都没说= =。 3 | ***/ 4 | 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | 10 | int main() { 11 | string a, b; cin >> a >> b; 12 | int len1 = a.length(), len2 = b.length(); 13 | if (len1 > len2) { 14 | int tmp = len1 - len2; 15 | string add = ""; 16 | while (tmp--) add += '0'; 17 | b = add + b; 18 | } 19 | reverse(a.begin(), a.end()); 20 | reverse(b.begin(), b.end()); 21 | string ans = b; 22 | char arr[] = {'J', 'Q', 'K'}; 23 | int end = a.length() <= b.length() ? a.length() : b.length(); 24 | 25 | for (int i = 0; i < end; ++i) { 26 | if (i % 2) { 27 | int tmp = b[i] - a[i]; 28 | if (tmp < 0) tmp += 10; 29 | ans[i] = '0' + tmp; 30 | } 31 | else { 32 | int tmp = ((a[i]-'0') + (b[i]-'0')) % 13; 33 | if (tmp > 9) ans[i] = arr[tmp-10]; 34 | else ans[i] = '0' + tmp; 35 | } 36 | } 37 | reverse(ans.begin(), ans.end()); 38 | cout << ans << endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /算法笔记/BFS解决矩阵块问题.cpp: -------------------------------------------------------------------------------- 1 | // 一个m*n的矩阵 分布着0和1 相邻(上下左右)的1构成块 单个1也算一块 问矩阵中共有几块 2 | // BFS 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | const int maxn = 100; 8 | struct node { 9 | int x, y; // 位置坐标 10 | }Node; 11 | 12 | int n, m; 13 | int matrix[maxn][maxn]; 14 | bool inq[maxn][maxn] = {false}; 15 | int X[4] = {0, 0, 1, -1}; 16 | int Y[4] = {1, -1, 0, 0}; // 对应上下左右走法 17 | 18 | bool judge(int x, int y) { // 判断位置x,y是否需要访问的1 19 | if (x >= n || x < 0 || y >= m || y < 0) return false; // 越界 20 | if (matrix[x][y] == 0 || inq[x][y]==true) return false; // 当前位置为0或已入过队 21 | return true; 22 | } 23 | 24 | // BFS函数访问位置(x, y)所在的块 将该块中所有1位置的inq都设置为true 25 | void BFS(int x, int y) { 26 | queue Q; 27 | Node.x = x, Node.y = y; // 当前节点坐标为x,y 28 | Q.push(Node); inq[x][y] = true; 29 | while (!Q.empty()) { 30 | node top = Q.front(); 31 | Q.pop(); 32 | for (int i = 0; i < 4; ++i) { // 循环四次 得到四个相邻位置 33 | int newX = top.x + X[i]; int newY = top.y + Y[i]; 34 | if (judge(newX, newY)) { 35 | Node.x = newX; Node.y = newY; 36 | Q.push(Node); inq[newX][newY] = true; 37 | } 38 | } 39 | } 40 | } 41 | 42 | int main() { 43 | scanf("%d %d", &n, &m); 44 | for (int x = 0; x < n; ++x) { 45 | for (int y = 0; y < m; ++y) scanf("%d", &matrix[x][y]); 46 | } 47 | int ans = 0; // 存放块数 48 | for (int x = 0; x < n; ++x) { 49 | for (int y = 0; y < m; ++y) { // 枚举每一个位置 50 | if (matrix[x][y] == 1 && !inq[x][y]) { 51 | ans++; BFS(x, y); // 访问整个块 将整个块的1的inq都标记为true 52 | } 53 | } 54 | } 55 | printf("%d", ans); return 0; 56 | } 57 | -------------------------------------------------------------------------------- /算法笔记/C++字符串全排列.cpp: -------------------------------------------------------------------------------- 1 | //输入一个字符串 输出该字符串字符的全排序 无顺序要求 2 | 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | const int maxn = 100; int n; 8 | char arr[maxn] = {0}; int hashtable[128] = {0}; 9 | char ans[maxn] = {0}; 10 | 11 | void generateP(int index) { 12 | if (index == n) { 13 | for (int i = 0; i < n; ++i) printf("%c", ans[i]); 14 | printf("\n"); return; 15 | } 16 | for (int i = 0; i < n; ++i) { 17 | if (!hashtable[arr[i]]) { 18 | ans[index] = arr[i]; hashtable[arr[i]] = 1; 19 | generateP(index+1); 20 | hashtable[arr[i]] = 0; 21 | } 22 | } 23 | } 24 | 25 | int main() { 26 | scanf("%s", arr); 27 | n = strlen(arr); 28 | generateP(0); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /算法笔记/C++数字按升序全排列.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n; // n是要排列的数字个数 5 | const int maxn = 10; int p[maxn+1]; 6 | int hashtable[maxn+1] = {0}; 7 | void generateP(int index) { // index是当前要排的位子序号 8 | if (index == n) { // 0~n-1位已经排完了 一种排列完成 递归出口outlet 9 | for (int i = 0; i < n; ++i) { 10 | printf("%d", p[i]); 11 | } printf("\n"); return; 12 | } 13 | //index还没到最后一位 按序枚举index处可以安置的数字 14 | for (int num = 1; num <= n; ++num) { // 枚举的功能就是得到 1开头的全排列(12xx..13..) 2开头的全排列... 15 | if (!hashtable[num]) { // 这个数字没被占用 16 | p[index] = num; hashtable[num] = 1; 17 | generateP(index+1); // index处安排好了 后面的index+1~n-1位 不管他 交给递归完成 18 | hashtable[num] = 0; // 后面都安排上了 已经在outlet输出了 解除当前该处数字的占用 19 | } 20 | } 21 | } 22 | 23 | int main() { 24 | n = 3; 25 | generateP(0); // 从第0位开始排列 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /算法笔记/DFS解决背包问题.cpp: -------------------------------------------------------------------------------- 1 | // 背包问题 dfs解决 2 | #include 3 | const int maxn = 30; 4 | int n, v, maxValue=-1; // 物品件数n 背包容量v 最大价值maxValue 5 | int w[maxn], c[maxn]; // 每件物品重量w[i] 每件物品价值c[i] 6 | // index为当前处理物品的序号 sumW为当前总重量 sumC为当前总价值 7 | void DFS(int index, int sumW, int sumC) { 8 | if (index == n) { // 已经完成对n件物品的选择 (死胡同) 9 | if (sumW <= v && sumC > maxValue) maxValue = sumC; 10 | return; 11 | } 12 | // 岔道口 13 | DFS(index+1, sumW, sumC); // 不选第index件物品 14 | if (sumW + w[index] <= v) { // 未超过容量时 才继续选第index件物品 15 | if (sumC + c[index] > maxValue) maxValue = sumC + c[index]; 16 | DFS(index+1, sumW+w[index+1], sumC+c[index]); 17 | } 18 | } 19 | 20 | int main() { 21 | scanf("%d %d", &n, &v); 22 | for (int i = 0; i < n; ++i) scanf("%d", &w[i]); 23 | for (int i = 0; i < n; ++i) scanf("%d", &c[i]); 24 | DFS(0, 0, 0); // 初始为第0件物品 25 | printf("%d\n", maxValue); 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /算法笔记/N皇后问题_回溯法.cpp: -------------------------------------------------------------------------------- 1 | // n皇后问题 回溯法 2 | // 有可能当已经放置了一些皇后 剩下的皇后怎么放都不合法 直接返回上层 3 | // 在到达递归边界前的某层 由于一些事实导致不需要子递归了 就可以直接返回上一层 4 | #include 5 | using namespace std; 6 | 7 | int abs(int a) { 8 | if (a >= 0) return a; 9 | else return 0-a; 10 | } 11 | int cnt = 0; // 合法方案数 12 | const int maxn = 100; int n; 13 | int P[maxn] = {0}, hashtable[maxn] = {0}; 14 | 15 | void generateP(int index) { 16 | if (index == n+1) { 17 | cnt++; return; // 能到达这里的一定是合法的 18 | } 19 | 20 | for (int r = 1; r <= n; ++r) { 21 | if (!hashtable[r]) { // 枚举行号 22 | bool flag = true; // flag为true 当前皇后不会和之前皇后冲突 23 | for (int pre = 1; pre < index; ++pre) { // 遍历之前 列 的皇后 行号 24 | if (abs(index - pre) == abs(r - P[pre])) { 25 | flag = false; break; 26 | } 27 | } 28 | if (flag) { // 如果可以把皇后放在r行 29 | P[index] = r; hashtable[r] = 1; 30 | generateP(index+1); 31 | hashtable[r] = 0; 32 | } 33 | } 34 | } 35 | } 36 | 37 | int main() { 38 | n = 8; 39 | generateP(1); 40 | printf("%d\n", cnt); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /算法笔记/N皇后问题_高效暴力法.cpp: -------------------------------------------------------------------------------- 1 | // n皇后问题 暴力法(高效枚举+递归实现排列) 2 | // 普通暴力枚举 n^2里取n的排列数 3 | // 高效枚举 每一列只会有有一个皇后->只会有一个行号->枚举行号的全排列再检验是否合法 4 | // P[n] 下标i是列号 值P[i]是行号 5 | #include 6 | using namespace std; 7 | 8 | int abs(int a) { 9 | if (a >= 0) return a; 10 | else return 0-a; 11 | } 12 | int cnt = 0; // 合法方案数 13 | const int maxn = 100; int n; 14 | int P[maxn] = {0}, hashtable[maxn] = {0}; 15 | 16 | void generateP(int index) { 17 | if (index == n+1) { // 一个排列已经生成 18 | bool flag = true; // 该排列是否有效 19 | for (int i = 1; i <= n; ++i) { // i是列 20 | for (int j = i+1; j <= n; ++j) { 21 | if (abs(i-j) == abs(P[i] - P[j])) flag = false; // 如果在一条对角线上 22 | } 23 | } 24 | if (flag) { 25 | cnt++; return; 26 | } 27 | } 28 | for (int r = 1; r <= n; ++r) { 29 | if (!hashtable[r]) { // 枚举行号 30 | P[index] = r; hashtable[r] = 1; 31 | generateP(index+1); 32 | hashtable[r] = 0; 33 | } 34 | } 35 | } 36 | 37 | int main() { 38 | n = 8; 39 | generateP(1); 40 | printf("%d\n", cnt); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /算法笔记/区间贪心.cpp: -------------------------------------------------------------------------------- 1 | // 区间贪心 用局部最优推得全局最优 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int maxn = 110; 7 | struct interval { 8 | int x, y; 9 | }I[maxn]; 10 | 11 | bool cmp(interval a, interval b) { 12 | if (a.x != b.x) return a.x > b.x; 13 | else return a.y < b.y; 14 | } 15 | 16 | int main() { 17 | int n; 18 | while (scanf("%d", &n) && n != 0) { 19 | for (int i = 0; i < n; ++i) scanf("%d %d", &I[i].x, &I[i].y); 20 | } 21 | sort(I,I+n, cmp); 22 | // ans记录不相交区间个数 lastx记录上一个被选中区间的左端点 23 | int ans = 1, lastx = I[0].x; 24 | for (int i = 1; i < n; ++i) { 25 | if (I[i].y <= lastx) { // 区间选点问题只需要把这句改成 I[i].y < lastx 26 | lastx = I[i].x; ans++; 27 | } 28 | } 29 | printf("%d\n", ans); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /算法笔记/好朋友_并查集例题.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | const int N = 110; 3 | 4 | int father[N]; 5 | int isRoot[N] = {0}; 6 | 7 | void init(int n) { 8 | for (int i = 1; i <= n; ++i) father[i] = i; 9 | } 10 | 11 | int findFather(int x) { // 查找x所在集合的根节点 12 | int a = x; // x循环后会变成root 先存储原来的值 13 | while (father[x] != x) x = father[x]; 14 | // 路径压缩 15 | while (father[a] != a) { 16 | int b = a; 17 | father[b] = x; // 不能一步到位把father[a]改成x 不然还怎么用father[a]更新a= = 18 | a = father[a]; 19 | } 20 | return x; 21 | } 22 | 23 | void Union(int a, int b) { 24 | int faA = findFather(a); 25 | int faB = findFather(b); 26 | if (faA != faB) father[faA] = faB; 27 | } 28 | 29 | int main() { 30 | int n, m, f1, f2; 31 | scanf("%d %d", &n, &m); 32 | init(n); 33 | for (int i = 0; i < m; ++i) { 34 | scanf("%d %d", &f1, &f2); 35 | Union(f1, f2); // 合并朋友1和朋友2所在集合 36 | } 37 | // for (int i = 1; i <= n; ++i) isRoot[findFather(i)] = 1; 38 | for (int i = 1; i <= n; ++i) isRoot[father[i]] = 1; // 路径压缩过以后应该可以这样写 39 | int ans = 0; 40 | for (int i = 1; i <= n; ++i) ans += isRoot[i]; 41 | printf("%d\n", ans); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /读书笔记/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/merelydust/PAT-Advanced-Level/b2c9b916f3bdd0f2509e2636c06668a675f1f091/读书笔记/.DS_Store --------------------------------------------------------------------------------