一坨狗屎,但是拓展性和鲁棒性竟然不错?有兴趣的可以去洛谷 P1236 ↗ 交一发。
使用了奇怪的函数指针写法,表达式树也建得一坨。
//
// main.cpp
// 24-Point
//
// Created by Leo Xia on 2026/3/20.
//
#include <bits/stdc++.h>
using namespace std;
const int P = 4, T = 24;
const bool LUOGU = false;
int a[P][P],ind[P][P],cnt;
struct Node
{
int l,r,v;// lson, rson, v (int or + - * /)
}ans[P<<2];
int add(const int&x,const int&y){return x+y;}
int sub(const int&x,const int&y){return x-y;}
int mul(const int&x,const int&y){return x*y;}
int div(const int&x,const int&y)
{
if(y==0||x%y!=0)
throw "Bad Operation";
return x/y;
}
using Op = int (*const)(const int&x,const int&y);
Op comop[2]={add,mul};
Op uncop[2]={sub,div};
const char icomop[2]={'+','*'};
const char iuncop[2]={'-','/'};
inline void forward(const int&d,const int&i,const int&j)
{
for(int l=0,r=0;l<P-d;l++)
{
if(l==i||l==j)continue;
r++;
a[d+1][r]=a[d][l];
}
}
inline void backward(const int&d,const int&i,const int&j)
{
for(int l=0,r=0;l<P-d;l++)
{
if(l==i||l==j)continue;
r++;
ind[d][l]=ind[d+1][r];
}
}
bool dfs(int d)
{
if(d>=3)
{
return a[d][0]==T;
}
for(int i=0;i<P-d;i++)
{
for(int j=i+1;j<P-d;j++)
{
for(int k=0;k<2;k++)
{
a[d+1][0]=comop[k](a[d][i],a[d][j]);
if(LUOGU&&a[d+1][0]<=0)continue;
forward(d,i,j);
if(dfs(d+1))
{
ans[ind[d+1][0]]={cnt+1,cnt+2,icomop[k]};
ind[d][i]=++cnt;ind[d][j]=++cnt;
backward(d,i,j);
return true;
}
}
for(int k=0;k<2;k++)
{
try{a[d+1][0]=uncop[k](a[d][i],a[d][j]);}
catch(...){continue;}
if(LUOGU&&a[d+1][0]<=0)continue;
forward(d,i,j);
if(dfs(d+1))
{
ans[ind[d+1][0]]={cnt+1,cnt+2,iuncop[k]};
ind[d][i]=++cnt;ind[d][j]=++cnt;
backward(d,i,j);
return true;
}
}
for(int k=0;k<2;k++)
{
try{a[d+1][0]=uncop[k](a[d][j],a[d][i]);}
catch(...){continue;}
if(LUOGU&&a[d+1][0]<=0)continue;
forward(d,j,i);
if(dfs(d+1))
{
ans[ind[d+1][0]]={cnt+1,cnt+2,iuncop[k]};
ind[d][j]=++cnt;ind[d][i]=++cnt;
backward(d,i,j);
return true;
}
}
}
}
return false;
}
inline int lvl(const char&op)
{
if(op=='*'||op=='/')return 1;
if(op=='+'||op=='-')return 0;
return 2;
}
pair<string,int> print(int x)
{
if(ans[x].l&&ans[x].r)
{
pair<string,int>lres=print(ans[x].l),rres=print(ans[x].r),ret={"",lvl(ans[x].v)};
if(lres.second<lvl(ans[x].v))ret.first+='('+lres.first+')';
else ret.first+=lres.first;
ret.first+=(char)ans[x].v;
if(rres.second<lvl(ans[x].v))ret.first+='('+rres.first+')';
else ret.first+=rres.first;
return ret;
}
return {to_string(ans[x].v),2};//0 means + -, 1 means * /, 2 means number
}
Op c2op(const char&op)
{
switch (op) {
default:
case '+':
return comop[0];
case '*':
return comop[1];
case '-':
return uncop[0];
case '/':
return uncop[1];
}
}
int luogu_print(int x)
{
if(ans[x].l&&ans[x].r)
{
int lres=luogu_print(ans[x].l),rres=luogu_print(ans[x].r);
if(ans[x].v=='+'||ans[x].v=='*')
if(lres<rres)swap(lres,rres);
int ret=c2op(ans[x].v)(lres,rres);
cout<<lres<<(char)ans[x].v<<rres<<'='<<ret<<'\n';
return ret;
}
return ans[x].v;
}
int main()
{
for(int i=0;i<P;i++)
{
cin>>a[0][i];
}
if(!dfs(0))
{
cout<<"No answer!";
return 0;
}
for(int i=0;i<P;i++)ans[ind[0][i]].v=a[0][i];
cout<<print(0).first;
// luogu_print(0);
return 0;
}cpp