"Zero Sum" and "Sum to N"(DFS枚举)

题目:Zero Sum

这道题卡了好久好久了~~~

Description
Consider the sequence of digits from 1 through N (where N=9) in increasing order: 1 2 3 … N.

Now insert either a ‘+’ for addition or a ‘-’ for subtraction or a ’ ’ [blank] to run the digits together between each pair of digits (not in front of the first digit). Calculate the result that of the expression and see if you get zero.

Write a program that will find all sequences of length N that produce a zero sum.

Input
Multiple test cases. Each case contains a single line with the integer N ( 3 ≤ N ≤ 9 ).

Output
For each case, in ASCII order, show each sequence that can create 0 sum with a ‘+’, ‘-’, or ’ ’ between each pair of numbers.

Output a blank line after each case.

Sample Input
7

Sample Output
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

题意:

有‘+’、‘-’、‘ ’三种运算符,(空格的意思:比如2 3就是23),使1~n的总和为0。

题解:

用DFS枚举就OK了,
关键是如何去求最后的结果,进而才能去判断是否等于0。
‘ ’的处理是关键,用cnt保存最近的一个连续的整数,不将该数进行运算,sum表示cnt之前的运算结果。

/*AC7ms*/
#include<stdio.h>
#include<string.h>
int n;
char str[25];
void dfs(int i,int sum,int cnt)
{
    if(i==n)
    {
        if(sum+cnt==0)printf("%s\n",str);
        return;
    }
    str[2*i-1]=' ';
    dfs(i+1,sum,cnt>0?cnt*10+i+1:cnt*10-i-1);
    str[2*i-1]='+';
    dfs(i+1,sum+cnt,i+1);
    str[2*i-1]='-';
    dfs(i+1,sum+cnt,-i-1);

}
int main()
{
    while(~scanf("%d",&n))
    {
        memset(str,0,sizeof(str));
        for(int i=0;i<n;i++)
            str[i*2]=i+'1';
        dfs(1,0,1);
        puts("");
    }
    return 0;
}

oj标程代码:

/*AC63ms*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int n;
/* evaluate the string s as arithmetic and return the sum */
int eval(char *s)
{
    int term, sign, sum;
    char *p;
    
    sign = 1;
    term = 0;
    sum = 0;
    for(p=s; *p; p++) {
        switch(*p){
        case '+':
        case '-':
            sum += sign*term;
            term = 0;
            sign = *p == '+' ? 1 : -1;
            break;
        case ' ':
            break;
        default:    /* digit */
            term = term*10 + *p-'0';
        }
    }
    sum += sign*term;
    return sum;
}
/*
 * Insert + - or space after each number, and then
 * test to see if we get zero.  The first k numbers have
 * already been taken care of.
 */
void search(char *s, int k)
{
    char *p;

    if(k == n-1) {
        if(eval(s) == 0)
            printf("%s\n", s);
        return;
    }

    for(p=" +-"; *p; p++) {
        s[2*k+1] = *p;
        search(s, k+1);
    }
}

int main()
{
    int i;
    char str[30];

    while( scanf("%d", &n) != EOF )
    {
        strcpy(str, "1 2 3 4 5 6 7 8 9");
        str[2*n-1] = '\0';    /* chop string to only have first n numbers */

        search(str, 0);
        printf("\n");
    }
    return 0;
}

题目:Sum to N

Description
Find all ways + or - can be substituted for the @ symbol in a prototype equation like the one below such that the expression is true for a specified N (4 ≤ N ≤ 24). Count the number of distinct arrangements.

-1 @ 2 @ 3 @ 4 @ 5 … @ N-2 @ N-1 = N

Input
多测试用例。

A single line with the integer N.

Output
A single line with the integer that is the number of distinct ways the expression can be made true.

Sample Input
8

Sample Output
4
Hint
Namely:
-1 - 2 - 3 - 4 + 5 + 6 + 7 = 8
-1 - 2 + 3 + 4 + 5 + 6 - 7 = 8
-1 + 2 - 3 + 4 + 5 - 6 + 7 = 8
-1 + 2 + 3 - 4 - 5 + 6 + 7 = 8

#include<iostream>
using namespace std;
int ans,n,k;
char a[30];
void dfs(int i,int sum)
{
    if(i==n-1){ ///错误写法:if(i==n-1&&sum==n)ans++,return;这样写的话当i==n-1但sum!=n时不会进入该if语句,所以不能return
        if(sum==n){
            ans++;
            a[++k]='=';
            for(int q=0;q<=k;q++)
                cout<<a[q]<<q+1;
            cout<<endl;
            k--;
        }
        return;
    }
    a[++k]='-';
    dfs(i+1,sum-i-1);
    k--;
    a[++k]='+';
    dfs(i+1,sum+i+1);
    k--;

    return;
}
int main()
{
    while(!(cin>>n).eof())
    {
        ans=0;
        a[0]='-';
        dfs(1,-1);
        cout<<ans<<endl;
    }
    return 0;
}

以上代码运行结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值