给出一个数字N,对于数字序列 1,2,3 ... N。现在在其中插入“+”, "-", " ",使得表达式的和为M。" "的含义是把相邻的两个数字组成一个数。例如:1 + 2 3 - 4,含义是:1 + 23 - 4 = 20。
给出N和M,求出所有合法的序列的个数。
两个整数N,M ( 1 <= N <= 7, -100 <= M <= 100)
合法序列的个数
7 0
6
样例中的六种合法序列
1+2-3+4-5-6+7
1+2-3-4+5+6-7
1-2 3+4+5+6+7
1-2 3-4 5+6 7
1-2+3+4-5+6-7
1-2-3-4-5+6+7
//动态方程(有点难理解):当前种类=符号位加号+符号为减号+没有符号的种类
//dp(before,des,n,ex)= dp(before - 1, before, res + des,1) + dp(before - 1, before, res - des,1) + dp(before - 1, before*pow(10, ex)+des, res,ex+1);
// before: 需要判定的符号前面的数字的个数,初始为8
// des: 需要判定的符号后面的数字,初始为9
// n:方程右边的结果
// ex:阶乘数,因为符号有三种可能,加号,减号,或者没有,如果没有,那么ex就用于计算当前值
#include<iostream>
#include<cmath>
using namespace std;
int dp(int before, int des, int res, int ex) {
if (before == 0) {
if (des == res) {
return 1;
}
else {
return 0;
}
}
else {
return dp(before - 1, before, res + des, 1) + dp(before - 1, before, res - des, 1) + dp(before - 1, before*pow(10, ex) + des, res, ex + 1);
}
}
int main() {
int m,n;
cin >>m>>n;
cout << dp(m-1, m, n, 1);
} dfs解法
#include <iostream>
using namespace std;
int n, m;
int dfs(int sum, int current,int step) {
//当前和,当前位,当前数字(步数)
if (step == n + 1) {
if (sum == m&¤t == step) {
return 1;
}
else return 0;
}
//当当前位为一的时候,不允许减操作,如1 2 3 得到-15,通过-12-3是不允许的。同理1也不能得到-1
int temp = current;
while (temp > 9 ) {
temp = temp / 10;
}
if(temp ==1) return dfs(sum + current, step + 1, step + 1) + dfs(sum, current * 10 + step + 1, step + 1);
else return dfs(sum + current, step + 1,step+1) + dfs(sum - current, step + 1,step+1) + dfs(sum, current *10+ step +1,step+1);
}
int main() {
cin >> n >> m;
cout << dfs(0, 1,1);
system("pause");
return 0;
}
""""
DFS,用了eval直接字符串转表达式
"""
def dfs(s, n, m, step):
s += str(step)
if step == n:
if eval(s) == m:
return 1
return 0
return dfs(s + '+', n, m, step + 1) + dfs(s + '-', n, m, step + 1) + dfs(s, n, m, step + 1)
if __name__ == "__main__":
n, m = map(int, input().strip().split())
ans = dfs("", n, m, 1)
print(ans)
#include <stdio.h>
int n,m,count=0;
void getcount(int sum,int num,int step){ //分别为 当前和 当前数字 当前步数
if(step == n+1){
if(sum == m && num == step) //当num!=step时说明上一次有num*10....的存在,sum值没有改变
count ++;
return;
}
int temp = num; //判断num首位是否为1
while(temp > 9)
temp = temp/10;
//为1则不能进行减运算,1无法变为-1
//两种情况下按照题目意思进行穷举
if(temp == 1){
getcount(sum+num, step+1, step+1);
getcount(sum, num*10+step+1, step+1);
}
else{
getcount(sum+num, step+1, step+1);
getcount(sum-num, step+1, step+1);
getcount(sum, num*10+step+1, step+1);
}
}
int main(){
scanf("%d %d", &n,&m);
getcount(0,1,1); //初始条件下sum为0,当前步数已经数字均为1
printf("%d", count);
return 0;
} import java.util.Scanner;
public class Main {
private static int num;
private static int target;
private static int count=0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
num = scanner.nextInt();
target = scanner.nextInt();
dfs(0, 1);
System.out.println(count);
}
private static void dfs(int sum,int p){
if (sum==target&&p==num+1)
count++;
int t=0;
for (int i = p; i <=num; i++,t*=10) {
t+=i;
dfs(sum+t,i+1);
if (p!=1){
dfs(sum-t,i+1);
}
}
}
}
#include<iostream>
#include<cmath>
using namespace std;
/* 由后向前确定符号
* 0+1 ----(b-1)? b ? a = m
* 情况1. 0+1 ----(b-1) ?b + a = m 0+1 ----(b-1)? b = m-a
情况2. 0+1 ----(b-1) ?b - a = m 0+1 ----(b-1)? b = m+a
情况3. 0+1 ----(b-1) ?ba = m 0+1 ----(b-1)? ba = m
*/
int Solution(int b, int a, int digit, int m) {
// b 是待定符号前的数字 个位数
// a 是待定符号后的数字
// digit a的位数,用来确定ba的数值 ba=b * pow(10, digit) + a
// m 为等式的右值
if (0 == b) // // 递归基,1前隐含0+1,首个符号确定为加号
{
if (a == m) return 1;
else return 0;
}
else // 递归
{
return Solution(b - 1, b, 1, m - a) // b 与 a 之间是加号,对应情况1
+ Solution(b - 1, b, 1, m + a) // b 与 a 之间是减号,对应情况2
+ Solution(b - 1, b * pow(10, digit) + a, digit + 1, m); // b 与 a 之间无符号,对应情况3
}
}
int main() {
int n, m, cnt = 0;
cin >> n >> m;
cnt = Solution(n - 1, n, 1, m);
cout << cnt << endl;
return 0;
} #include<bits/stdc++.h>
using namespace std;
char cal[3] = {' ', '+', '-'};
vector<string> res;
int extract_str(string s) {
int res = 0;
string tmp;
for(int i = s.length() - 1; i >= 0 ; i--) {
if(s[i] == '+')
{res += atoi(tmp.c_str());tmp.clear();}
else if(s[i] == '-')
{res -= atoi(tmp.c_str());tmp.clear();}
else if(s[i] == ' ') continue;
else tmp = string(1, s[i]) + tmp;
}
return res + atoi(tmp.c_str());
}
void dfs(int pos, int N, string cur) {
if(pos == N - 1) {
string tmp = "1";
for(int i = 1; i < N ; i++) {
tmp.push_back(cur[i-1]);
tmp.push_back(i + '1');
}
res.push_back(tmp);
return;
}
for(int i = 0; i < 3; i++){
cur.push_back(cal[i]);
dfs(pos+1, N, cur);
cur.pop_back();
}
}
int main() {
int N, M; scanf("%d%d", &N, &M);
string empty = "";
dfs(0, N, empty);
int cnt = 0;
for(int i = 0; i < res.size(); i++)
if(extract_str(res[i]) == M) cnt++;
cout<<cnt<<endl;
}
/*
7 0
*/ #include<bits/stdc++.h>
using namespace std;
int n,m,cnt=0;
void DFS(int sum, int p){
if(sum==m && p==n+1)
cnt++;
int t = 0;
for(int i=p;i<=n;i++,t*=10){
t += i;
DFS(sum+t, i+1);
if(p!=1)
DFS(sum-t,i+1);
}
}
int main(){
cin>>n>>m;
DFS(0,1);
cout<<cnt<<endl;
return 0;
}
package main
import (
"fmt"
"strconv"
)
func main() {
var n,m int
fmt.Scan(&n,&m)
ans:=0
var dfs func(string,int)
dfs=func(s string,idx int){
if idx==n+1{
if cal(s)==m{
ans++
}
return
}
dfs(s+"+"+strconv.Itoa(idx),idx+1)
dfs(s+"-"+strconv.Itoa(idx),idx+1)
dfs(s+strconv.Itoa(idx),idx+1)
}
dfs("1",2)
fmt.Print(ans)
}
func cal(s string)int{
arr1,arr2:=[]int{},[]byte{}
pre:=""
for _,ch:=range []byte(s){
if ch=='+'||ch=='-'{
x,_:=strconv.Atoi(pre)
arr1=append(arr1,x)
arr2=append(arr2,ch)
pre=""
}else{
pre+=string(ch)
}
}
x,_:=strconv.Atoi(pre)
arr1=append(arr1,x)
ans:=arr1[0]
for i:=1;i<len(arr1);i++{
if arr2[i-1]=='+'{
ans+=arr1[i]
}else{
ans-=arr1[i]
}
}
return ans
}
#include <iostream>
#include <vector>
using namespace std;
// 创建新的数组, used[i]表示当前数字前面是否是 “ ”
void MakeNewVector(vector<int> & used, vector<int>& cur_nums, vector<int> & new_nums) {
new_nums.push_back(cur_nums[0]);
for (int i = 1; i < used.size(); ++i) {
// 如果当前第i-1后面是空格
if (used[i]) {
// 将最后一个和当前cur_numns[i]合成一个
new_nums[new_nums.size() - 1] = new_nums[new_nums.size() - 1] * 10 + cur_nums[i];
}
else {
new_nums.push_back(cur_nums[i]);
}
}
}
int sum_nums(vector<int>& nums, int S) {
int sum = 0;
for (int num : nums) {
sum += num;
}
if ((S + sum) % 2 == 1 || sum < abs(S)) {
return 0;
}
int bagSize = (S + sum) / 2;
vector<int> dp(bagSize + 1, 0);
dp[0] = 1;
for (int i = 0; i < nums.size(); i++) {
for (int j = bagSize; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
return dp[bagSize];
}
void BackStrack(vector<int>& cur_nums, vector<int>& used, int pos, int N, int target, int& sum) {
// 如果已经遍历完
if (pos == N) {
vector<int> new_nums;
MakeNewVector(used, cur_nums, new_nums);
// 对cur_nums,找合法种数
int temp = new_nums[0];
// 如果pos不为1,将cur_nums[1] 去掉
new_nums.erase(new_nums.begin());
// 更新当前的合法序列个数
sum += sum_nums(new_nums, target - temp);
return;
}
// 对于该位置有合并和不合并两种选择
for (int i = 0; i <= 1; ++i) {
// 对 pos 这个位置进行 “ ”
if (i) {
// + " "
// 将对应的used[i] --> 1 添加 “ ”
used[pos] = 1;
BackStrack(cur_nums, used, pos + 1, N, target, sum);
// = " "
used[pos] = 0;
}
else {
// 直接传递当前的数组
BackStrack(cur_nums, used, pos + 1, N, target, sum);
}
}
}
// 回溯 + 01背包动态规划
int main() {
int N, target, sum = 0;
// 输入 N 的大小
cin >> N >> target;
vector<int> nums(N, 1);
// N个数 N-1个空位,所以pos从1开始
vector<int> used(N, 0);
// 变成递增数组
for (int i = 1; i < nums.size(); ++i) {
nums[i] = nums[i - 1] + 1;
}
// 针对于 + - “ ”,来说,如果直接回溯,四种状态,时间复杂度是3^(N-1), 对 + - 变成背包问题,然后 “ ”采用回溯的方式来组合
BackStrack(nums, used, 1, N, target, sum);
cout << sum << endl;
}
// 64 位输出请用 printf("%lld")
import java.util.Scanner;
public class Main {
private int count = 0;
// 根据表达式计算值
public int calc(String expr){
int sum = 0;
StringBuilder sb = new StringBuilder();
// 重新整合表达式,即将带有" "的部分进行合并
for(int i = 0 ; i < expr.length() ; i++){
if(expr.charAt(i) != ' '){
sb.append(expr.charAt(i));
}
}
String expr2 = sb.toString();
// 分离数字部分
String[] nums = expr2.split("[+,-]");
// 分离运算符部分
String[] ops = expr2.split("\\d");
int numsIndex = 1;
sum = Integer.parseInt(nums[0]);
// 测试中发现分离运算符后会出行空值,于是遇到空值跳过
for(int i = 0 ; i < ops.length ; i++){
if(ops[i].equals("")){
continue;
}
if(ops[i].equals("+")){
sum += Integer.parseInt(nums[numsIndex]);
} else {
sum -= Integer.parseInt(nums[numsIndex]);
}
numsIndex++;
}
return sum;
}
// 回溯法
// target -> 求和目标值,也就是输入的M n->整数序列上限,也就是输入的N current->当前的数 expr->计算表达式
public void dfs(int target, int n, int current, String expr){
// 当前数越界,返回
if(current > n){
return;
}
// 符合target,记录并返回
if(current == n && calc(expr) == target){
count++;
return;
}
dfs(target, n, current+1, expr+"+"+(current+1));
dfs(target, n, current+1, expr+"-"+(current+1));
dfs(target, n, current+1, expr+" "+(current+1));
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int m = cin.nextInt();
Main main = new Main();
main.dfs(m,n,1,"1");
System.out.println(main.count);
}
}
#include<bits/stdc++.h>
using namespace std;
int N,M;
void dfs(int st,int cur,int & res)
{
if(st==N+1 && cur==M)
{
res++;
return;
}
int num=0;
for(int i=st;i<=N;i++)
{
num+=i;
dfs(i+1,cur+num,res);
if(st>1)
dfs(i+1,cur-num,res);
num*=10;
}
}
int main()
{
while(cin>>N>>M)
{
int res=0;
dfs(1,0,res);
cout<<res<<endl;
}
return 0;
} #include<bits/stdc++.h>
using namespace std;
int n, m,c=0;
void dfs(int sum, int step)
{
int i = 0, t = 0;
if (sum == m && step == n + 1)c++;
for (int i = step; i <= n; i++)
{
t += i;
dfs(sum + t, i + 1);
if (step > 1)dfs(sum - t, i + 1);
t *= 10;
}
}
int main()
{
cin >> n >> m;
dfs(0, 1);
cout << c << endl;
return 0;
} //刚学的回溯法 试试水。没一楼大神那么牛逼。
#include<stdio.h>
(737)#include<stdlib.h>
int n,m;//定义全局变量 n m;
void fun(char op[],int sum,int prevadd,int a[],int i,int &count)//引用型参数count 用于统计符合条件个数 并回传
{
if(i==n)
{
if(sum==m)
{
/*
printf("%d",a[0]);
for(int j=1;j<n;j++)
{
if(op[j]!=' ')
printf("%c",op[j]);
printf("%d",a[j]);
}
printf("==%d\n",m);
*/
count++;
}
return;
}
op[i]='+';
sum+=a[i];
fun(op,sum,a[i],a,i+1,count);
sum-=a[i];
op[i]='-';
sum-=a[i];
fun(op,sum,-a[i],a,i+1,count);
sum+=a[i];
op[i]=' ';
sum-=prevadd;
int tmp;
if(prevadd>0)
tmp=prevadd*10+a[i];
else
tmp=prevadd*10-a[i];
sum+=tmp;
fun(op,sum,tmp,a,i+1,count);
sum-=tmp;
sum+=prevadd;
}
int main()
{
int *a;
char *op;
int count=0;
scanf("%d%d",&n,&m);
a=(int*)malloc(sizeof(int)*n);
op=(char*)malloc(sizeof(char)*n);
for(int i=0;i<n;i++)
a[i]=i+1;
fun(op,a[0],a[0],a,1,count);
printf("%d",count);
} n,t=[int(i) for i in input().split()] l='' for i in range(1,n+1):l+='%d'%(i) class solution: def __init__(self, t): self.res = 0 self.t = t def find(self, l, dp=['+', 0, 0], i=0): if i == len(l) - 1: a, b, c = dp if a == '+': tmp = c + int(l[b:i + 1]) else: tmp = c - int(l[b:i + 1]) if tmp == self.t: self.res += 1 return self.find(l, dp, i + 1) a, b, c = dp if a == '+': tmp = c + int(l[b:i + 1]) self.find(l, ['+', i + 1, tmp], i + 1) self.find(l, ['-', i + 1, tmp], i + 1) else: tmp = c - int(l[b:i + 1]) self.find(l, ['+', i + 1, tmp], i + 1) self.find(l, ['-', i + 1, tmp], i + 1) s = solution(t) s.find(l) print(s.res)
var line=readline().split(' ').map(Number)
var n=line[0]
var sum=line[1]
var arr=new Array(n+1).join('0').split('');
arr.map((item,i)=>{
arr[i]=i+1
});
// 两层遍历
var num=0;
var label=['+','-',''];
function dfs(arr){
var myarr=[];
if(arr.length==1){
return arr
}
if(arr.length==2){
for(var j=0;j<3;j++){
myarr.push(arr[0]+label[j]+arr[1])
}
return myarr;
}
// 否则
for(var j=0;j<3;j++){
var tem=dfs(arr.slice(1));
for(var k=0;k<tem.length;k++){
myarr.push(arr[0]+label[j]+tem[k])
}
}
return myarr;
}
var myarr=dfs(arr)
// console.log(myarr)
for(var item in myarr){
if(eval(myarr[item])==sum){
num++;
}
}
console.log(num) import sys N, M = sys.stdin.readline().strip().split() N = int(N) M = int(M) nums = [i for i in range(N+1)] ans = 0 def dfs(N, M, cur, sign, res, i): global ans if i > N: res += cur*sign if res == M: ans += 1 return dfs(N, M, nums[i], 1, res+cur*sign, i+1) dfs(N, M, nums[i], -1, res+cur*sign, i+1) dfs(N, M, cur*10+nums[i], sign, res, i+1) dfs(N, M, 1, 1, 0, 2) print(ans)
#include<stdio.h>
#include<string>
#include<iostream>
#include<set>
#include<vector>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
int res_count = 0;
int m;
int n;
void check_eq(int cur_eq, int step)
{
if (step > n)
return;
if (step == n)
{
if (cur_eq == m)
{
res_count++;
return;
}
}
if(step <= n-2){
check_eq(cur_eq + ((step + 1) * 10 + (step + 2)), step + 2);
check_eq(cur_eq - ((step + 1) * 10 + (step + 2)), step + 2);
}
check_eq(cur_eq + (step + 1), step + 1);
check_eq(cur_eq - (step + 1), step + 1);
//check_eq(cur_eq * 10 + (step + 1), step + 1);
}
int main()
{
cin >> n >> m;
check_eq(1, 1);
char s[500];
if( n >1 )
check_eq(12, 2);
printf("%d", res_count);
return 0;
}