本机环境win10+gcc-5.4
先给出这道题的简化做法,假如只有'+'、'-'这两种操作,显然这道题简单了许多。
我们可以通过枚举数字与数字之间的总共n-1个符号,假设n为5,就是枚举符号0000、0001、0010、0011、0100、0101。。。1111,1111对于二进制来表示就是数字(2^(n-1))-1
对于确定了的符号可以直接得出运算结果。
复杂度为(2^n)*(n)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,sum,out,q1[20];//q1的[1,n)存n-1个符号
ll cal(){
ll res=1,i=1;
if(out)cout <<"1";
for(i=2;i<=n;i++){
if(q1[i-1]==0){
if(out)cout << "+"<<i;
res+=i;
}else{
if(out)cout <<"-"<<i;
res-=i;
}
}
if(out)cout <<endl;
if(res==0)sum++;
}
int d[2]={0,1};//这里存符号的种数
ll dfs(ll x){
if(x==n){
cal();
}else{
for(int i=0;i<2;i++){//枚举3种符号
q1[x]=d[i];
dfs(x+1);
}
}
}
int main(){
//freopen("in.txt","w",stdout);
n=9;
//out=1; //把这里注释去掉就是打印枚举的结果
dfs(1);
cout << sum <<endl;
return 0;
}
这道题完整版我们需要枚举多一种符号,也就是' ',把两个数字连在一起,我们可以通过预判断q1[i+1]也就是下一个符号是否为0(对应' ')来判断是否把两个数字相连接,从而得到最终答案。
复杂度(3^n)*(n)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,sum,out,q1[20];//q1的[1,n)存n-1个符号
ll cal(){
ll res=1,num=1,i=1,len;
while(q1[i]==0){
len=i+1;
while(len)num*=10,len/=10; //判断下次相连数字的位数来判断乘几次10
num+=i+1;
i++;
}
res=num;
if(out)cout << num;
for(;i<n;i++){
num=i+1;
if(q1[i]==1){
while(q1[i+1]==0){
i++,len=i+1;
while(len){
num*=10;len/=10;
}1
num+=i+1;
}
if(out)cout <<"+"<<num;
res+=num;
}else if(q1[i]==2){
while(q1[i+1]==0){
i++,len=i+1;
while(len){
num*=10;len/=10;
}
num+=i+1;
}
if(out)cout <<"-"<<num;
res-=num;
}
}
if(out)cout <<endl;
if(res==0)sum++;
}
int d[3]={0,1,2};//这里存符号的种数
ll dfs(ll x){
if(x==n){
cal();
}else{
for(int i=0;i<3;i++){//枚举3种符号
q1[x]=d[i];
dfs(x+1);
}
}
}
int main(){
freopen("in.txt","w",stdout);
n=9;
q1[n]=3;
//out=1; //把这里注释去掉就是打印枚举的结果
dfs(1);
cout << sum <<endl;
return 0;
}
)