有趣的求和

题目链接: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\n",answer);
		for(int i=0;i<answer;i++){
			cout<<q[i]<<endl;
		}
	}
	else{
		printf("0");
	}
	return 0;
} 

最后说一下,这道题目中并没有说关于最后输出的操作方式的顺序的问题,那么也就是说应该什么顺序输出都行,但结果并不是这样,本程序的dfs部分,我是先执行的减法,再执行的加法,如果顺序颠倒后,就会WA,这是这道题的不足吧

posted @ 2020-08-24 11:23  ice--cream  阅读(183)  评论(0编辑  收藏  举报