洛谷 P1236 算24点
题目描述
几十年前全世界就流行一种数字游戏,至今仍有人乐此不疲.在中国我们把这种游戏称为“算24点”。您作为游戏者将得到4个1~9之间的自然数作为操作数,而您的任务是对这4个操作数进行适当的算术运算,要求运算结果等于24。
您可以使用的运算只有:+,-,*,/,您还可以使用()来改变运算顺序。注意:所有的中间结果须是整数,所以一些除法运算是不允许的(例如,(2*2)/4是合法的,2*(2/4)是不合法的)。下面我们给出一个游戏的具体例子:
若给出的4个操作数是:1、2、3、7,则一种可能的解答是1+2+3*7=24。
输入输出格式
输入格式:
只有一行,四个1到9之间的自然数。
输出格式:
如果有解的话,只要输出一个解,输出的是三行数据,分别表示运算的步骤。其中第一行是输入的两个数和一个运算符和运算后的结果,第二行是第一行的结果和一个输入的数据、运算符、运算后的结果,或者是另外两个数的输出结果;第三行是前面的结果第二行的结果或者剩下的一个数字、运算符和“=24”。如果两个操作数有大小的话则先输出大的。
如果没有解则输出“No answer!”
如果有多重合法解,输出任意一种即可。
注:所有运算结果均为正整数
输入输出样例
说明
感谢chenyy提供special judge
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int a,b,c,d,f1,f2,f3,f4; char s[5]={'0','+','-','*','/'}; int ans[10000],pos[10000]; void dfs(int num,int tot){ if(num>24||num<0) return ; if(num==24&&tot==3){ int sum=ans[0]; for(int i=1;i<=tot;i++){ printf("%d%c%d=",max(sum,ans[i]),s[pos[i]],min(sum,ans[i])); if(pos[i]==1) sum+=ans[i],cout<<sum<<endl; if(pos[i]==2) sum-=ans[i],cout<<sum<<endl; if(pos[i]==3) sum*=ans[i],cout<<sum<<endl; if(pos[i]==4) sum/=ans[i],cout<<sum<<endl; } exit(0); } if(!f1){ if(num>=a&&a!=1){ f1=1;ans[tot+1]=a;pos[tot+1]=4;dfs(num/a,tot+1);f1=0; } f1=1;ans[tot+1]=a;pos[tot+1]=1;dfs(num+a,tot+1);f1=0; f1=1;ans[tot+1]=a;pos[tot+1]=2;dfs(num-a,tot+1);f1=0; f1=1;ans[tot+1]=a;pos[tot+1]=3;dfs(num*a,tot+1);f1=0; } if(!f2){ if(num>=b&&b!=1){ f2=1;ans[tot+1]=b;pos[tot+1]=4;dfs(num/b,tot+1);f2=0; } f2=1;ans[tot+1]=b;pos[tot+1]=1;dfs(num+b,tot+1);f2=0; f2=1;ans[tot+1]=b;pos[tot+1]=2;dfs(num-b,tot+1);f2=0; f2=1;ans[tot+1]=b;pos[tot+1]=3;dfs(num*b,tot+1);f2=0; } if(!f3){ if(num>=c&&c!=1){ f3=1;ans[tot+1]=c;pos[tot+1]=4;dfs(num/c,tot+1);f3=0; } f3=1;ans[tot+1]=c;pos[tot+1]=1;dfs(num+c,tot+1);f3=0; f3=1;ans[tot+1]=c;pos[tot+1]=2;dfs(num-c,tot+1);f3=0; f3=1;ans[tot+1]=c;pos[tot+1]=3;dfs(num*c,tot+1);f3=0; } if(!f4){ if(num>=d&&d!=1){ f4=1;ans[tot+1]=d;pos[tot+1]=4;dfs(num/d,tot+1);f4=0; } f4=1;ans[tot+1]=d;pos[tot+1]=1;dfs(num+d,tot+1);f4=0; f4=1;ans[tot+1]=d;pos[tot+1]=2;dfs(num-d,tot+1);f4=0; f4=1;ans[tot+1]=d;pos[tot+1]=3;dfs(num*d,tot+1);f4=0; } } int main(){ scanf("%d%d%d%d",&a,&b,&c,&d); f1=1;ans[0]=a;dfs(a,0);f1=0; f2=1;ans[0]=b;dfs(b,0);f2=0; f3=1;ans[0]=c;dfs(c,0);f3=0; f4=1;ans[0]=d;dfs(d,0);f4=0; cout<<"No answer!"; }
一开始做的时候,以为按顺序来就可以了,后来发现可能出现这种情况:1 1 2 7 (1+2)*(1+7)=24 然后就会gg。
所以这个题目的思路应该是每次抽出两张牌,尽行任意一种操作,然后进行组合,判断是否等于24就可以了。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> using namespace std; int f; int a1[4],a2[4]; int a[4],vis[4],pos[4]; void check(){ for(int i=0;i<4;i++) if(a[i]==24){ f=1;break; } if(f==1){ for(int i=0;i<3;i++){ cout<<a1[i]; if(pos[i]==1) cout<<"+"<<a2[i]<<"="<<a1[i]+a2[i]<<endl; if(pos[i]==2) cout<<"-"<<a2[i]<<"="<<a1[i]-a2[i]<<endl; if(pos[i]==3) cout<<"*"<<a2[i]<<"="<<a1[i]*a2[i]<<endl; if(pos[i]==4) cout<<"/"<<a2[i]<<"="<<a1[i]/a2[i]<<endl; } exit(0); } } void dfs(int t){ if(t==1) {check();return;} if(t>1) for(int i=0;i<4;i++) if(a[i]==24) return; for(int i=0;i<4;i++) for(int j=0;j<4;j++) if(vis[j]==0&&a[i]>=a[j]&&i!=j){ a1[4-t]=a[i];a2[4-t]=a[j]; a[i]=a[i]+a[j];vis[j]=1;pos[4-t]=1; if(a[i]>0&&vis[i]==0) dfs(t-1); vis[j]=0;a[i]-=a[j]; a1[4-t]=a[i];a2[4-t]=a[j]; a[i]=a[i]-a[j];vis[j]=1;pos[4-t]=2; if(a[i]>0&&vis[i]==0) dfs(t-1); vis[j]=0;a[i]+=a[j]; a1[4-t]=a[i];a2[4-t]=a[j]; a[i]=a[i]*a[j];vis[j]=1;pos[4-t]=3; if(a[i]>0&&vis[i]==0) dfs(t-1); vis[j]=0;a[i]/=a[j]; if(a[i]%a[j]==0){ a1[4-t]=a[i];a2[4-t]=a[j]; a[i]=a[i]/a[j];vis[j]=1;pos[4-t]=4; if(a[i]>0&&vis[i]==0) dfs(t-1); vis[j]=0;a[i]*=a[j]; } } } int main(){ for(int i=0;i<4;i++) scanf("%d",&a[i]); dfs(4); if(f==0) cout<<"No answer!"; }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。