CoderXL's Blog

Back

一坨狗屎,但是拓展性和鲁棒性竟然不错?有兴趣的可以去洛谷 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
24 点计算器
https://blog.leosrealms.top/blog/oi/2026-03-20-24-points-calculator
Author CoderXL
Published at 2026年3月20日
Comment seems to stuck. Try to refresh?✨