我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html
题目传送门:https://www.luogu.org/problemnew/show/P1236
算(24)点应该是大家耳熟能详的游戏了……
这题(SPJ),要求把两个要运算的数字较大的放在前面输出……
然后爆搜数字顺序和运算符就可以了……
真~暴力美学
时间复杂度:(O(4!*4^3))
空间复杂度:(O(n))
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
bool bo[5];
int a[5],sta[5],sign[4],fake[5];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
void print() {
int sum=sta[1];
for(int i=2;i<=4;i++) {
if(sum<sta[i])swap(sum,sta[i]);
if(sign[i-1]==1)printf("%d+%d=%d
",sum,sta[i],sum+sta[i]),sum+=sta[i];
if(sign[i-1]==2)printf("%d-%d=%d
",sum,sta[i],sum-sta[i]),sum-=sta[i];
if(sign[i-1]==3)printf("%d*%d=%d
",sum,sta[i],sum*sta[i]),sum*=sta[i];
if(sign[i-1]==4)printf("%d/%d=%d
",sum,sta[i],sum/sta[i]),sum/=sta[i];
}
}//输出
void check() {
memcpy(fake,sta,sizeof(fake));
int now=fake[1];
for(int i=2;i<=4;i++) {
if(now<fake[i])swap(now,fake[i]);//记得要把大的数字放在前面判
if(sign[i-1]==1)now=now+fake[i];
if(sign[i-1]==2)now=now-fake[i];
if(sign[i-1]==3)now=now*fake[i];
if(sign[i-1]==4) {
if(fake[i]==0)return;
if(now%fake[i])return;
now/=fake[i];
}
}
if(now==24) {print();exit(0);}
}//判断是否可以算出24
void make_sign(int id) {
if(id==3) {check();return;}
for(int i=1;i<=4;i++)
sign[id+1]=i,make_sign(id+1);
}//搜完运算符就判是否可行
void dfs(int id) {
if(id==4) {
for(int i=1;i<=4;i++)
sign[1]=i,make_sign(1);
return;
}//搜完数字搜运算符
for(int i=1;i<=4;i++)
if(!bo[i]) {
bo[i]=1,sta[id+1]=a[i];
dfs(id+1);
bo[i]=0;
}//爆搜数字
}
int main() {
a[1]=read(),a[2]=read();
a[3]=read(),a[4]=read();//读入四个数
for(int i=1;i<=4;i++) {
bo[i]=1;sta[1]=a[i];
dfs(1);
bo[i]=0;//爆搜
}puts("No answer!");//如果爆搜出不了结果就No answer!
return 0;
}