64,646
社区成员
发帖
与我相关
我的任务
分享
//给出2~12个数加括号改变运算顺序的所有方案
//例如:
//输入2,输出
//(1+2)
//输入3,输出
//((1+2)+3)
//(1+(2+3))
//输入4,输出
//(((1+2)+3)+4)
//((1+(2+3))+4)
//((1+2)+(3+4))
//(1+((2+3)+4))
//(1+(2+(3+4)))
//依此类推
//
//解题思路:
//后缀表达式转中缀表达式
//后缀表达式总是前2个是数字, 最后一个是运算符, 中间是各 n-2 个数字和运算符,
//程序里用一个bit表示后缀表达式中是出现数字还是运算符, 1表示数字, 0表示运算符,
//check检查是否是合法的表达式
//output把后缀表达式转成中缀表达式输出
//中缀表达式好像除了给人看也没啥用, 如果是具体计算就完全不用转中缀表达式了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int b1c( unsigned x ) {
x = (x&0x55555555) + ((x&0xaaaaaaaa)>>1);
x = (x&0x33333333) + ((x&0xcccccccc)>>2);
x = (x&0x0f0f0f0f) + ((x&0xf0f0f0f0)>>4);
x = (x&0x00ff00ff) + ((x&0xff00ff00)>>8);
x = (x&0x0000ffff) + ((x&0xffff0000)>>16);
return x;
}
int check(int n, int v) {
int c = 1;
n-=2;
while (n--) {
if (v & (1<<(2*n + 1)))
++c;
else if (--c < 0)
return 0;
if (v & (1<<2*n))
++c;
else if (--c < 0)
return 0;
}
return 1;
}
void output(int idx, int n, int v) {
char s_expr[16][80], expr_r[80], expr[80], *pi, *po;
int stack[16], ne = 1, ns = 2;
strcpy(s_expr[0], ".");
stack[0] = stack[1] = 0;
n = 2 * (n-2);
while (n--) {
if (v & (1<<n)) {
stack[ns++] = 0;
} else {
--ns;
sprintf(s_expr[ne], "(%s+%s)", s_expr[stack[ns-1]], s_expr[stack[ns]]);
stack[ns-1] = ne++;
}
}
sprintf(expr_r, "(%s+%s)", s_expr[stack[0]], s_expr[stack[1]]);
for (n = 0, pi = expr_r, po = expr; *pi; ++pi, ++po) {
if ('.' == *pi) {
++n;
if (n < 10) {
*po = '0' + n;
} else {
*po++ = '1';
*po = '0' + n - 10;
}
} else {
*po = *pi;
}
}
*po = 0;
printf("%8d: %s\n", idx, expr);
}
int main(int argc, char* argv[]) {
int n = 8, nmx, i, idx = 0;
if (argc == 2) n = atoi(argv[1]);
if (n < 2 || n > 16) n = 8;
nmx = 1 << 2 * (n-2);
for (i = 0; i < nmx; ++i) {
if (b1c(i) == n - 2 && check(n, i))
output(idx++, n, i);
}
return 0;
}