由5个数算23点的问题。
另外还引申了一个4个数算24点的加括号的问题。到底有多少种。有想清楚的同学可以交流下...自己才疏学浅。
只考虑一种加括号的形式,一开始没弄懂这句话什么意思。写了一个所有加括号的情况。
相当于暴搜,把所有情况,所有加括号的形式写出来。
#include<iostream>
const int goal=23;
int arrays[5];
using namespace std;
bool pointgame(int n){
if(n==1){
if(arrays[0]==goal)
return true;
else
return false;
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
int a,b;
a=arrays[i];
b=arrays[j];
arrays[j]=arrays[n-1];
arrays[i]=a+b;
if(pointgame(n-1))
return true;
arrays[i]=a*b;
if(pointgame(n-1))
return true;
arrays[i]=a-b;
if(pointgame(n-1))
return true;
arrays[i]=b-a;
if(pointgame(n-1))
return true;
arrays[i]=a;
arrays[j]=b;
}
}
return false;
}
int main()
{
while(1){
int i,flag;
for(i=0;i<5;i++)
cin>>arrays[i];
for(flag=0,i=0;i<5;i++)
if(!arrays[i])
flag++;
if(flag==5)
break;
if(pointgame(5))
cout << "Possible\n";
else
cout << "Impossible\n";
}
return 0;
}
后面一来就TLE了。因为考虑了所有加括号的情况。而此题目只要求一种加括号的情况,不过上面的代码也可以改成任意m个数算n点的方法。
只要改一下goal与array代的个数就行。除法也类似于上面,只要最后加进去就行了。
而网上的深搜+回溯的方式就只考虑其中一种方式,首先我们要选择一个点作为起点,接下来依次选择第二个,第三个数....直到算的值为23点就跳出
#include<iostream>
#include<cstring>
const int goal=23;
const int MAX=6;
using namespace std;
int Array[MAX];
bool vis[MAX],flag;
void dfs(int cur,int value){
if(cur==5&&value==goal){
flag=1;
return;
}
else{
if(flag)
return;
for(int i=0;i<5;i++){
if(!vis[i]){
vis[i]=true;
dfs(cur+1,value+Array[i]);
dfs(cur+1,value-Array[i]);
dfs(cur+1,value*Array[i]);
vis[i]=false;
}
}
}
}
int main()
{
while(1){
int i,num;
flag=0;
for(i=0;i<5;i++)
cin >> Array[i];
for(i=0,num=0;i<5;i++)
if(Array[i]==0)
num++;
if(num==5)
break;
for(i=0;i<5;i++){
memset(vis,false,sizeof(vis));
vis[i]=true;
dfs(1,Array[i]);
}
if(flag)
cout << "Possible\n";
else
cout << "Impossible\n";
}
return 0;
}
做完此题后有一个疑惑,算24点游戏的4个数字究竟有多少种排法?4个数的排列有4!,三个运算符,每个运算符有4种就是3^4,其中有5种加括号的形式,则为4!*(3^4)*5=7680种排法,但是我的疑问是如((2+(3*4))+5)这种加括号的形式不就是相当于(((3*4)+2)+5)这种形式吗?因为数是任意排的。则说明其中有重叠的情况,然后就不知道怎么样去算了。如果谁知道的话交流下呗。