主要使用了dfs的算法,比较麻烦的是如何去重,去重第一步可以用set来保存式子,然后再去多余的括号,然后在用另一个set去重。但是做到真正的去重还是比较麻烦,如果有好的建议的博友,可以私信。比如1*2*3*4与2*3*1*4其实是重复的2*(1+2)*4与2*4*(1+2)是重复的。

  代码如下:

  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<set>
#include<iterator>
using namespace std;
int cmp(int a,int b){return a<=b;}
void moveBrak(char* str);
int m[4];
//使用set主要是为了去重
set<string> ss;

void dfs(int sum,int cur,int i,string strSum,string strCur)
{
    if(i==3)
    {
        char strTemp[100];
        if(sum+cur==24){
            sprintf(strTemp,"%s + %s = 24",strSum.c_str(),strCur.c_str());
            ss.insert(strTemp);
        }
        else if(sum - cur==24){
            sprintf(strTemp,"%s - %s = 24",strSum.c_str(),strCur.c_str());
            ss.insert(strTemp);
        }
        else if(sum * cur==24){
            sprintf(strTemp,"%s * %s = 24",strSum.c_str(),strCur.c_str());
            ss.insert(strTemp);
        }
        else if(cur && sum%cur==0 && sum / cur == 24){
            sprintf(strTemp,"%s / %s = 24",strSum.c_str(),strCur.c_str());
            ss.insert(strTemp);
        }
        return;
    }
    char strTemp[100];
    sprintf(strTemp,"%d",m[i+1]);
    dfs(sum,cur+m[i+1],i+1,strSum,"( "+strCur+" + "+strTemp+" )");
    dfs(sum,cur-m[i+1],i+1,strSum,"( "+strCur+" - "+strTemp+" )");
    dfs(sum,cur*m[i+1],i+1,strSum ,strCur+" * "+strTemp);
    if(m[i+1] && cur%m[i+1]==0)
        dfs(sum,cur/m[i+1],i+1,strSum,strCur+" / "+strTemp);
    dfs(sum+cur,m[i+1],i+1,"( "+strSum+" + "+strCur+" )",strTemp);
    dfs(sum-cur,m[i+1],i+1,"( "+strSum+" - "+strCur+" )",strTemp);
    dfs(sum*cur,m[i+1],i+1, strSum+" * "+strCur,strTemp);
    if(cur && sum%cur==0)
        dfs(sum/cur,m[i+1],i+1,strSum+" / "+strCur,strTemp);
}

int main()
{
    while(~scanf("%d%d%d%d",&m[0],&m[1],&m[2],&m[3]))
    {
        ss.clear();
        sort(m,m+4,cmp);
        do
        {
            char strTemp[100];
            sprintf(strTemp,"%d",m[0]);
            string strSum = strTemp,strCur;
            sprintf(strTemp,"%d",m[1]);
            strCur = strTemp;
            dfs(m[0],m[1],1,strSum,strCur);
        }while(next_permutation(m,m+4));

        set<string>::iterator it = ss.begin();
        set<string> res;

        //去无效括号
        for(;it!=ss.end();it++)
        {
            char strTemp[100];
            strcpy(strTemp,it->c_str());
            moveBrak(strTemp);
            res.insert(strTemp);
        }

        int cnt = 0;
        it = res.begin();
        for(;it!=res.end();it++,++cnt)
            printf("%s\n",it->c_str());
        if(cnt) printf("总共有%d个算式\n",cnt);
        else    printf("没有符合条件的算式\n");
    }
    return 0;
}

void moveBrak(char* str)
{
    if(true) return;
    int len = strlen(str);
    //dev表示去掉的括号,left,right表示保留的括号
    char dev = '#',left = '$',right = '&';
    for(int i=0;i<len;++i)
    {
        if(str[i]==')')
        {
            int j = i-1;
            for(;j>=0;--j)
                if(str[j]=='(')
                    break;
            //是否去掉括号
            bool bDev = false;

            if(i<len-2&&(str[i+2]=='+'||str[i+2]=='-'))
                bDev = true;
            if(j>=2&&(str[j-2]=='+'))
                bDev = true;
            else if(j>=2&&(str[j-2]=='-'||str[j-2]=='*'||str[j-2]=='/'))
                bDev =  false;
            if(bDev)     str[i] = str[j] = dev;
            else         str[i] = right,str[j] = left;
        }
    }
    char strTemp[100];
    int k = 0;
    for(int i=0;i<len;++i)
    {
        if(str[i]==dev)
        {
            ++i;
            continue;
        }
        if(str[i]==left)
            strTemp[k++] = '(';
        else if(str[i]==right)
            strTemp[k++] = ')';
        else
            strTemp[k++] = str[i];
    }
    strTemp[k++] = '\0';
    memcpy(str,strTemp,k);
}