ACM 程序设计竞赛入门:第5讲 搜索题
acm搜索入门

int main(){ while(scanf("%d",&n)!=EOF){ memset(vis,0,sizeof(vis));
DFS(1); } return 0; }
}
} }
• DFS-两点是否连通问题 • 题(去年校赛):
• /web/showProblem?id=12 62
不可以! 时间复杂度O(n^2)
• • • • • •
if(sign) break;
} printf("%s\n",sign?"YES":"NO"); } return 0; }
• • • • • • • • • • • • • • • • • • • • • • • •
正确做法: #include<stdio.h> #include<string.h> const int MX=10000+5; int A[MX],vis[1000000+5]; int main(){ int n,i,j,k; while(scanf("%d%d",&n,&k)!=EOF){ memset(vis,0,sizeof(vis)); for(i=1;i<=n;i++){ scanf("%d",&A[i]); vis[A[i]]=1; } sign=false; for(i=1;i<=n;i++){ if(k-A[i]>=0&&vis[k-A[i]]==1){ sign=true; break; } } printf("%s\n",sign?"YES":"NO"); } return 0; }
ACM程序设计基础之搜索

3.搜索的变形
• • • • • • • • 3.1记忆化搜索 3.2迭代加深搜索 3.3双向广度优先搜索 3.4周界搜索 3.5优先队列广搜 3.6A*搜索 3.7IDA*搜索 3.8Alpha-Beta减枝搜索
3.1记忆化搜索
• 记忆化就是在搜索的过程中,对已算出 的节点关键值进行记忆化,以减少下次 再用到此节点时引起的重复搜索。
11
3 层 4 层
2 8 3 1 6 4 7 5
2 8 3 1 6 4 7 5
8 3 2 1 4 7 6 5
2 8 3 7 1 4 6 5
2 8 1 4 3 7 6 5
2 8 3 1 4 5 7 6
1 2 3 7 8 4 6 5
1 2 3 8 4 7 6 5
2 8 3 6 4 1 7 5
2 8 3 1 6 7 5 4
– 扩展结点时,DFS将所有子结点全部扩展出来,再 选取最新的一个结点进行扩展。 – 回溯搜索只扩展所有子结点的其中一个,然后再以 这一子结点去扩展下一个子结点,当某个结点不能 再扩展出新结点的时候,就删除这个结点,用其父 结点来扩展新的结点。 – DFS最后寻找解的路径,回溯搜索路径即解路径 – 占用内存少,只需存取当前的一条搜索路径。 – 要求所有解方案的问题 – 试探性求解问题中
• 标记数组也属于hash的一种 其中hash函数值就是数字本身
DFS的优化
• 如果只求一个可行解,那么找到以后就 可以返回了。 • 判重在有些时候是有必要的。
• 在搜索树上,把一些不可能存在可行解 或者更优解的树枝减掉。
剪枝
• 可行性剪枝 • 最优性剪枝
POJ1011 STICKS
• 已知一些等长的木棍被切成,n个短木棍.现在 要根据这些短木棍的长度来求接原来木棍的 长度,由于可能有多组解,因此 要求求出最短的 可能长度. • 小木棍的个数不超过64 • 如:9 5 2 1 5 2 1 5 2 1 • 原来的可能最短长度为: 6 • 5+1 5+1 5+1 2+2+2
acm编程比赛入门题目集

程序设计比赛试题主办方:迅翔计算机协会最少钱币数:【问题描述】这是一个古老而又经典的问题。
用给定的几种钱币凑成某个钱数,一般而言有多种方式。
例如:给定了6种钱币面值为2、5、10、20、50、100,用来凑15元,可以用5个2元、1个5元,或者3个5元,或者1个5元、1个10元,等等。
显然,最少需要2个钱币才能凑成15元。
你的任务就是,给定若干个互不相同的钱币面值,编程计算,最少需要多少个钱币才能凑成某个给出的钱数。
【要求】【数据输入】输入可以有多个测试用例。
每个测试用例的第一行是待凑的钱数值M(1 <= M <= 2000,整数),接着的一行中,第一个整数K(1 <= K <= 10)表示币种个数,随后是K 个互不相同的钱币面值Ki(1 <= Ki <= 1000)。
输入M=0时结束。
【数据输出】每个测试用例输出一行,即凑成钱数值M最少需要的钱币个数。
如果凑钱失败,输出“Impossible”。
你可以假设,每种待凑钱币的数量是无限多的。
【样例输入】156 2 5 10 20 50 10011 2【样例输出】2ImpossibleFeli 的生日礼物【问题描述】Felicia 的生日是11月1日(和Kitty是同一天生的哦)。
于是Feli请来Kitty一起过生日。
Kitty带来了最新款的“Kitty猫”玩具准备送给Feli,不过她说,这份礼物可不是白送的。
Feli要帮她一个忙,才能够得到心仪已久的玩具。
Kitty说,“Kitty猫”玩具已经卖出了n!个,n<=10^100 *_*,Kitty想知道确切的数字,而不是无聊的“一个数加个感叹号”。
Feli 听了大吃一惊。
要知道,算出n!是一个无比艰巨的任务。
Feli告诉Kitty,就算Feli算出n!,Kitty也看不下去,因为当n=20 时,计算机的长整型已经存不下了(Kitty只能接受1-9之间的数字)。
acm竞赛试题及答案

acm竞赛试题及答案ACM竞赛试题及答案1. 问题描述:给定一个整数数组,找出数组中没有出现的最小的正整数。
2. 输入格式:第一行包含一个整数n,表示数组的长度。
第二行包含n个整数,表示数组的元素。
3. 输出格式:输出一个整数,表示数组中没有出现的最小的正整数。
4. 样例输入:53 4 1 2 55. 样例输出:66. 问题分析:首先,我们需要理解题目要求我们找出数组中缺失的最小正整数。
这意味着我们需要检查数组中的每个元素,并确定最小的正整数是否在数组中。
7. 算法描述:- 遍历数组,使用一个哈希集合记录出现的数字。
- 从1开始,检查每个正整数是否在哈希集合中,直到找到不在集合中的最小正整数。
8. 代码实现:```pythondef find_missing_positive(nums):seen = set()for num in nums:if num <= 0:continuewhile num in seen or num > len(nums):num += 1seen.add(num)return min(set(range(1, len(nums) + 1)) - seen)```9. 测试用例:- 输入:[3, 4, -1, 1]- 输出:210. 答案解析:在给定的测试用例中,数组[3, 4, -1, 1]中没有出现的最小正整数是2。
这是因为-1不是正整数,所以可以忽略。
数组中已经出现了1和3,所以下一个最小的正整数就是2。
11. 注意事项:- 确保数组中的元素是整数。
- 考虑数组中可能包含0或负数的情况。
- 算法的时间复杂度应尽可能低。
12. 扩展思考:- 如果数组非常大,如何优化算法?- 如果数组中的元素可以是浮点数,算法应该如何修改?13. 参考答案:- 针对大数组,可以考虑使用更高效的数据结构,如平衡二叉搜索树。
- 如果元素是浮点数,需要先将其转换为整数,然后再进行处理。
acm大赛试题及答案

acm大赛试题及答案ACM大赛试题及答案1. 题目一:字符串反转问题描述:编写一个程序,输入一个字符串,输出其反转后的字符串。
输入格式:输入包含一个字符串,字符串长度不超过100。
输出格式:输出反转后的字符串。
示例:输入:hello输出:olleh答案:```pythondef reverse_string(s):return s[::-1]input_string = input().strip()print(reverse_string(input_string))```2. 题目二:计算阶乘问题描述:编写一个程序,输入一个非负整数n,输出n的阶乘。
输入格式:输入包含一个非负整数n,n不超过20。
输出格式:输出n的阶乘。
示例:输入:5输出:120答案:```pythondef factorial(n):if n == 0:return 1else:return n * factorial(n - 1)n = int(input())print(factorial(n))```3. 题目三:寻找最大数问题描述:给定一个包含n个整数的数组,找出数组中的最大数。
输入格式:输入包含一个整数n,表示数组的大小,随后是n个整数。
输出格式:输出数组中的最大数。
示例:输入:5 1 2 3 4 5输出:5答案:```pythonn = int(input())numbers = list(map(int, input().split()))max_number = max(numbers)print(max_number)```4. 题目四:判断闰年问题描述:编写一个程序,输入一个年份,判断该年份是否为闰年。
输入格式:输入包含一个整数,表示年份。
输出格式:如果输入的年份是闰年,则输出"Yes",否则输出"No"。
示例:输入:2000输出:Yes答案:```pythonyear = int(input())if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):print("Yes")else:print("No")```5. 题目五:斐波那契数列问题描述:编写一个程序,输入一个非负整数n,输出斐波那契数列的第n项。
ACM 程序设计竞赛入门:第5讲 搜索题

2020/12/10
17
深入分析
p,q的范围其实可在2—50000(why?) 然而,这是最小的范围吗?
考虑大于10000的某个质数,不妨设为Q,另一 个质数为P,则:
如果P<10,P/Q<0.001 如果P>10,P*Q>100000
而考虑到a,b的取值范围(1<=a<=b<=1000) 可知min(a/b)=0.001
1.先访问左子树 2.再访问右子树 3.最后访问根结点 4.对于左右子树的访问也要满足以上规则
示例如下:
2020/12/10
26
1
2
3
4
56
7
以上二叉树的后根遍历序列是:??
4、5、 2、 6、7 、 3、 1
2020/12/10
27
(4)层次遍历
对树的访问次序是:
1.先访问根结点 2.再访问根结点的子节点(即第二层节点) 3.再访问第三层节点
同时,要求: p*q<=m<=100000
所以无论如何质数都不能超过10000。(事实上,
不会超过9091)
2020/12/10
18
搜索时的技巧:
搜索顺序很重要。建议从大往小搜 ( num:质数的个数 ) for (i=num-1;i>=0;i--) for (j=i;j<=num-1;j++) ……
(6)若后继节点中某一个是目标节点,则找 到一个解,成功退出。否则转向(2)循环。
2020/12/10
41
例、节点搜索示意图
OPEN
S
CLOSED
S
A, H,
A
R, F,
acm竞赛试题及答案

acm竞赛试题及答案ACM(Association for Computing Machinery)竞赛是一项全球性计算机科学竞赛,旨在锻炼参赛者的问题解决能力和编程技巧。
每年都有数千名来自不同学校的学生参加这一挑战。
本文将提供一些最近的ACM竞赛试题以及相应的答案,帮助读者了解和学习竞赛题目的类型和解题思路。
1. 问题描述给定一个由N个整数组成的数组A,请编写一个程序,找出数组中两个不同元素的差的最小值。
2. 输入格式- 第一行包含一个整数N,表示数组A的长度。
- 第二行包含N个以空格分隔的整数,表示数组A中的元素。
3. 输出格式输出一个整数,表示数组中两个不同元素的差的最小值。
4. 示例输入:51 52 9 12输出:15. 解题思路该问题可以通过对数组进行排序,并比较相邻两个数的差值来求解。
首先,将数组A进行升序排序。
然后,遍历排序后的数组,依次计算相邻两个数的差值,并记录其中的最小值。
最后,返回这个最小差值即可。
6. 代码实现```pythondef min_difference(nums):nums.sort() # 对数组进行升序排序min_diff = float('inf') # 初始化最小差值为正无穷大for i in range(len(nums)-1):diff = abs(nums[i] - nums[i+1]) # 计算相邻两个数的差值min_diff = min(min_diff, diff) # 更新最小差值return min_diff# 输入处理N = int(input())A = list(map(int, input().split()))# 调用函数并输出结果result = min_difference(A)print(result)```7. 答案解析对给定的数组进行排序后,遍历数组计算相邻两个数的差值,并记录其中的最小值。
上述代码中,首先将数组A进行升序排序,然后使用一个变量`min_diff`来记录最小差值。
入门acm试题及答案

入门acm试题及答案入门ACM试题及答案1. 问题描述给定一个整数数组,请找出数组中第二大的数。
2. 输入格式第一行包含一个整数n,表示数组的大小。
第二行包含n个整数,表示数组元素。
3. 输出格式输出数组中第二大的数。
4. 样例输入53 14 1 55. 样例输出46. 问题分析首先,我们需要读取数组的大小和元素。
然后,使用两个变量分别存储数组中的最大值和第二大的值。
遍历数组,更新这两个变量的值。
7. 算法实现```pythondef find_second_max(n, arr):max_val = float('-inf')second_max = float('-inf')for num in arr:if num > max_val:second_max = max_valmax_val = numelif num > second_max and num != max_val:second_max = numreturn second_max# 读取输入n = int(input())arr = list(map(int, input().split()))# 输出结果print(find_second_max(n, arr))```8. 注意事项- 确保数组中至少有两个不同的元素。
- 考虑数组中可能存在相等的最大值的情况。
9. 测试用例- 输入:`5 3 1 4 1 5`,输出:`4`- 输入:`4 10 10 20 20`,输出:`10`- 输入:`3 7 5 3 5`,输出:`5`10. 总结本题考查了基本的数组操作和简单的逻辑判断,通过维护两个变量来跟踪最大值和第二大的值,可以高效地解决问题。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(2)中根遍历
对树的访问次序是:
1.先访问左子树 2.再访问根结点 3.最后访问右子树 4.对于左右子树的访问也要满足以上规则
示例如下:
2020/12/10
24
1
2
3
4
56
7
以上二叉树的中根遍历序列是:??
4、 2、 5、 1、 6、 3、 7
2020/12/10
分别有什么特点呢?
2020/12/10
21
(1)先根遍历
对树的访问次序是:
1.先访问根结点 2.再访问左子树 3.最后访问右子树 4.对于左右子树的访问也要满足以上规则
示例如下:
2020/12/10
22
1
2
3
4
56
7
以上二叉树的先根遍历序列是:??
1、2、4、5、3、6、7
2020/12/10
23
3.按上述思想流程应为
a.从1—100000中搜出质数 b.两层循环,试遍所有的组合(p,q可能相等) c.每种组合去判断是否符合条件,如是,将 p*q与当前最大值比较,判断,保存
2020/12/10
16
面临的问题:
超时!
从1—100000的质数运算约为1e+8,而这 只是准备工作。
因此,如不加以分析简化此题无法在规 定时间内出解
同时,要求: p*q<=m<=100000
所以无论如何质数都不能超过10000。(事实上,
不会超过9091)
2020/12/10
18
搜索时的技巧:
搜索顺序很重要。建议从大往小搜 ( num:质数的个数 ) for (i=num-1;i>=0;i--) for (j=i;j<=num-1;j++) ……
题目链接
Again
Sample Input
512 99999 999 999 1680 5 16 1970 1 1 2002 4 11 000
Sample Output 22 313 313 23 73 43 43 37 53
2020/12/10
14
获取有用信息
a.给定整数m,a,b(4 < m <= 100000 and 1 <= a <= b <= 1000)
b.需要找到两个数(不妨设为p,q)满足以下 条件:
p,q均为质数;
p*q<=m;
a/b <= p/q <= 1;
c.输出所有满足以上条件的p,q中乘积最大 的一对p,q
2020/12/10
15Βιβλιοθήκη 算法分析1.典型的搜索 从所有可能的p,q中寻找满足条件的一对
2.p,q的要求 p,q均为质数,且p<=q<=100000;
11
说明:
本题除了可以练习基本搜索算法,也是 练习字符串处理的好题目,题中用到的 相关知识点有:
求反串 求子串 字符串查找 求字符串长度
强烈推荐!!
2020/12/10
12
再来一道数值型搜索题
2020/12/10
13
HDOJ_1239
Calling Extraterrestrial Intelligence
第五讲 搜索题
2020/12/10
1
统计信息:
根据“信息学初学者之家”网站的统计,
Ural(俄罗斯的Ural州立大学的简称 ,那里设立 了一个Ural Online Problem Set,并且支持 Online Judge。 )的题目类型大概呈如下的分布 :
搜索 动态规划 贪心 构造 图论
约10% 约15% 约5% 约5% 约10%
——摘自《ACM竞赛之新人向导 》
2020/12/10
4
什么是搜索算法呢?
搜索算法是利用计算机的高性能来有目 的地穷举一个问题的部分或所有的可能情况 ,从而求出问题的解的一种方法。
搜索过程实际上是根据初始条件和扩展 规则构造一棵解答树并寻找符合目标状态的 节点的过程。
2020/12/10
5
预热一下:二分查找
2 3 4 5 6 8 12 20 32 45 65 74 86 95 100
head
mid
tail
2020/12/10
6
查找示意图:
A[1]~A[15]
A[1]~A[7]
A[9]~A[15]
A[1]~A[3] A[5]~A[7] A[1]~A[1] A[3]~A[3]
……
2020/12/10
7
思考:
计算几何 纯数学问题 数据结构 其它
约5%
约20%
约5% 约25%
2020/12/10
2
搜索题特点分析:
题意容易理解 算法相对固定 编程有路可循 竞赛必备知识
2020/12/10
3
引言
“算法中最基本和常用的是搜索,主要是回溯和
分支限界法的使用。这里要说的是,有些初学者 在学习这些搜索基本算法是不太注意剪枝,这是 十分不可取的,因为所有搜索的题目给你的测试 用例都不会有很大的规模,你往往察觉不出程序 运行的时间问题,但是真正的测试数据一定能过 滤出那些没有剪枝的算法。实际上参赛选手基本 上都会使用常用的搜索算法,题目的区分度往往 就是建立在诸如剪枝之类的优化上了。 ”
1、在一百万个元素里查找某个元素 大约需要比较多少次?
2、时间复杂度:O(logN)
2020/12/10
8
举例分析
从简单的字符串搜索讲起
2020/12/10
9
HDOJ_1238 Substrings
题目链接
Sample Input 2 3 ABCD BCDFF BRCD 2 rose orchid
Sample Output 2 2
2020/12/10
10
题目分析:
这是一道入门级别的搜索题,基本思想
比较简单,但是如果用最朴素的算法,
可能会超时如何降低算法的复杂度呢?
下面的算法如何:
先将字符串按长度从短到长排序,枚举 最短的字符串的子串,判断是否都是别 的字符串的子串,求出最大长度即可。
2020/12/10
2020/12/10
17
深入分析
p,q的范围其实可在2—50000(why?) 然而,这是最小的范围吗?
考虑大于10000的某个质数,不妨设为Q,另一 个质数为P,则:
如果P<10,P/Q<0.001 如果P>10,P*Q>100000
而考虑到a,b的取值范围(1<=a<=b<=1000) 可知min(a/b)=0.001
注意剪枝:
If ( a[j]>m || a[j]*a[i]>m || ( (double)a[i]/a[j])<s )
……
2020/12/10
19
真正的搜索题
迷宫搜索
2020/12/10
20
预备知识——树的遍历
树的遍历主要有如下四种方法:
1.先根/序遍历 2.中根/序遍历 3.后根/序遍历 4.层次遍历