POJ---1020:Dessert【爆搜】

 

FJ has a new rule about the cows lining up for dinner. Not only must the N (3 <= N <= 15) cows line up for dinner in order, but they must place a napkin between each pair of cows with a "+", "-", or "." on it. In order to earn their dessert, the cow numbers and the napkins must form a numerical expression that evaluates to 0. The napkin with a "." enables the cows to build bigger numbers. Consider this equation for seven cows: 

      1 - 2 . 3 - 4 . 5 + 6 . 7


This means 1-23-45+67, which evaluates to 0. You job is to assist the cows in getting dessert. (Note: "... 10 . 11 ...") will use the number 1011 in its calculation.) 

Input

One line with a single integer, N 

Output

One line of output for each of the first 20 possible expressions -- then a line with a single integer that is the total number of possible answers. Each expression line has the general format of number, space, napkin, space, number, space, napkin, etc. etc. The output order is lexicographic, with "+" coming before "-" coming before ".". If fewer than 20 expressions can be formed, print all of the expressions. 

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
6

题意:

输入一个n,在1-n两两之间依次插入一个运算符——‘+’,‘-’,‘.’,3.4 代表整型34。依次运算,统计结果为0的不同表达式,结果大于20,只用输出前20个表达式,最后一行还要输出符合条件的表达式的总数。运算符的优先级:‘+’>‘-'  >  '.'  。

题解:

DFS深搜,如果运算符是  '.'  就需要改变上一次的运算,因此要标记前一次计算结果sum和前一次的运算值cur(加了多少或减了多少)。

AC代码:

#include<iostream>
#include<cmath>
#include<math.h>
#include<cstdio>
using namespace std;
char arr[100];                    //表达式数组
char op[3]={'+','-','.'};
int num[30],n,ans,p,cur,sum;      //P代表表达式数组的移动
void dfs(int x,int cur,int sum)   //x代表存储数字的数组的下标
{
    if(!sum&&x==n-1)             //和为0且用了1-N
    {
        ans+=1;
        if(ans>20) return;     
        cout<<arr[0];
      for(int q=1;q<p;q++)
      {
          int r=arr[q]-'0';     //这样是为了存储时直接存两位数为一个字符
          if(r>=10)             //判断是不是两位数
            cout<<" "<<num[r-1];
          else cout<<" "<<arr[q];
      }
      cout<<endl;
        return ;
    }
    if(x==n-1) {               //到达边界
            return ;
    }
    for(int i=0;i<3;i++)       //遍历三个运算符
    {
        int t=sum,b=cur;       //存储sum和cur,回溯时带换回来(因为sum和cur都要更新)
        if(i==0)
            sum=sum+num[x+1],cur=num[x+1];  
        if(i==1)
            sum=sum-num[x+1],cur=-num[x+1];//更新sum和cur
         if(i==2){
            int dp;
            if(x+1>8) dp=2;                //判断下一位要运算的数的位数
            else dp=1;
            int tep=abs(cur)*pow(10*1.0,dp);
            if(cur>0)
            {
                sum=sum-cur+tep+num[x+1];   //上一次是加了一个数,先减去家的数,再加上新的数;
                    cur=tep+num[x+1];       //更新cur为加得的新的数
            }
            else
            {
                sum=sum-cur-tep-num[x+1];   //上一次是减,更新就相反
                    cur=-tep-num[x+1];
            }
        }
        arr[p++]=op[i];                     //先存储运算符
        arr[p++]=(num[x+1]+'0');            //存储数字,无论数字是一位还是两位,都存储为一个字符,只需要在输出时处理一下
        dfs(x+1,cur,sum);                   //DFS下一个数
        sum=t;                              //回溯
        cur=b;
        p-=2;                               //答案数组回溯两位,因为上面存了两次
    }
}
int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        num[i]=i+1;                       //存储1-N
        sum=1;                            //先把第一位数加起  
        arr[0]='1',p=1;                       //表达式第一位永远是1,p移到1
        dfs(0,1,1);
         cout<<ans;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值