前言
本文在于复习“穷举搜索”之递归算法。
一、英文原文题目
Write a program which reads a sequence A A A of n n n elements and an integer M M M, and outputs “yes” if you can make M M M by adding elements in A A A, otherwise “no”. You can use an element only once You are given the sequence A A A and q q q questions where each question contains M i M_i Mi.
二、中文题目翻译
现有长度为 n n n的数列 A A A和正整数 M M M。请编写一个程序,判断 A A A中任意几个元素相加是否能得到 m m m。 A A A中每个元素只能使用 1 1 1次。
三、输入及输出样例
1.输入
第
1
1
1行输入
n
n
n
第
2
2
2行输入
A
A
A的
n
n
n个整数
第
3
3
3行输入
q
q
q
第
4
4
4行输入整数
M
i
M_i
Mi
2.输出
输出个问题的答案,如果 A A A中元素相加能得到 m i m_i mi,则回答yes;反之,回答no.
3.示例
input | output |
---|---|
5 | no |
1 5 7 10 21 | no |
4 | yes |
2 4 17 8 | yes |
四、递归分割问题
代码片段如下,其中关键部分为递归结束条件:
bool solve(int i, int m) {
//递归结束条件
if(m == 0) return true;
if(i >= n) return false;
bool res = solve(i + 1, m) || solve(i + 1, m - A[i]);//第i个选或不选
return res;
}
具体迭代关系如下图所示,solve(i,m)
中i
代表递归深度(从0开始),而m
代表下一次的迭代的目标值。
我们在最后得到solve(i,0)
即为成功。
五、完整代码
#include<stdio.h>
int n, A[50];
//从输入值M中减去所选元素的递归函数
bool solve(int i, int m) {
//递归结束条件
if(m == 0) return true;
if(i >= n) return false;
bool res = solve(i + 1, m) || solve(i + 1, m - A[i]);//第i个选或不选
return res;
}
int main() {
int q, M, i;
scanf("%d", &n);//高效输入函数
for(i = 0; i < n; i++) scanf("%d", &A[i]);
scanf("%d", &q);
for(i = 0; i < q; i++) {
//输入一个判断一个
scanf("%d", &M);
if(solve(0, M)) printf("yes\n");
else printf("no\n");
}
return 0;
}
六、后记
第一次写博客,对于markdown一无所知,有诸多不适,望海涵。
如有建议也可在直接评论区留言。