题目链接:https://ac.nowcoder.com/acm/contest/6840/B
来源:牛客网
题目描述
输入一组数据,包含M个整数(3 <= M <= 20),它们只能进行加法或者减法操作,你判断前M-1个数进行加或减操作后,结果是否可以等于第M个数,若没有方法可以得到第M个数,则只输出一行,为0。反之则输出共有两部分,第一部分在第一行输出,表示有多少种方式可以得到第M个数,第二部分从第二行开始为从左到右依次执行的操作(要求输出所有方式)。
输入描述:
第一行输入M
第二行输入M个整数,M个整数相互之间用空格隔开
输出描述:
1、没有方法可以得到第M个数,则只输出一行,为0
2、第一行输出有多少方式得到第M个数,其余各行分别输出操作方式
示例1
输入
6
1 2 3 3 2 1
输出
4
--++
-+-+
+-+-
++--
说明
有四种方法可以得到想要的结果(这四种分别为:--++,-+-+,+-+-,++--),第一种是--++,即表示1-2-3+3+2=1,其余同理。
题解
这道题用dfs,稍微剪枝一下,如果此时的和加上后面所有的数的结果还比最后那个数小,那么就不再继续搜索。如果此时的和减去后面所有的数的结果还比最后那个数大,那么也不用继续搜索了。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
int map[25];
int n;
int answer;
char charc[25];
int sum[25];
vector<string> q;
inline void dfs(int x,int temp){
if(x==n){
if(temp==map[n]){
answer++;
string str="";
for(int i=2;i<n;i++){
str+=charc[i];
}
q.push_back(str);
return;
}
}
//剪枝
if(temp+sum[n-1]-sum[x-1]<map[n]){
return;
}
if(temp-sum[n-1]+sum[x-1]>map[n]){
return;
}
charc[x]='-';
dfs(x+1,temp-map[x]);
charc[x]='+';
dfs(x+1,temp+map[x]);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&map[i]);
}
//求前缀和
for(int i=1;i<n;i++){
sum[i]=sum[i-1]+map[i];
}
dfs(2,map[1]);
if(answer){
printf("%d
",answer);
for(int i=0;i<answer;i++){
cout<<q[i]<<endl;
}
}
else{
printf("0");
}
return 0;
}
最后说一下,这道题目中并没有说关于最后输出的操作方式的顺序的问题,那么也就是说应该什么顺序输出都行,但结果并不是这样,本程序的dfs部分,我是先执行的减法,再执行的加法,如果顺序颠倒后,就会WA,这是这道题的不足吧