大一新生,刚看题目觉得不难,试图暴力枚举,结果失败,遂放弃,打完后才反应过来是搜索,于是又重写了一遍,记于此提醒自己。
分析题目,这就是个3种不同的小球不重复排列组合的题,于是我简化了一下,让k为1,d为2,a为3开始排列组合,每组合出一种结果判断是否25层,最后输出所有符合的个数,简简单单。
最开始套了个模板,结果超时了一点
cpp#include<iostream>
using namespace std;
#define kk 5
#define dd -10
#define aa 2
int b[21]= {0},sum=0,book[4]= {0},sumn=0; //初始化数据数组,标记数组,总层数,满足的情况总数,一定是全局变量,因为每层递归需要用上一次的结果
int k,d,a,n;
//算法核心,一个简单的深度搜索
void dfs(int s) {
if(s==n+1) { //如果到结尾了,判断层数是否等于25
sum=0;
for(int i=1;i<=n;i++){
if(b[i]==1) sum+=kk; //计算层数
if(b[i]==2) sum+=dd;
if(b[i]==3) sum+=aa;
if(sum<0) sum=0; //低于0层也是0层
if(sum>25) sum=25; //高于25层也是25层
}
if(sum==25) sumn++; //如果层数满足,总数加一
return;
}
//每一位开始递归
for(int j=1; j<=3; j++) {
if(book[j]) { //如果还有此种数据就把它扔一个进数组去
b[s]=j;
book[j]--; //该种数据个数减一
dfs(s+1); //递归判断下一位
book[j]++; //再倒着把这种数据捡回来
}
}
return;
}
//主函数
int main() {
cin>>k>>d>>a;
n=k+d+a;
book[1]=k; //初始化标记数组,存储k,d,a的个数
book[2]=d;
book[3]=a;
dfs(1); //从第一位开始递归
cout<<sumn;
return 0;
}
我一看,这个判断层数没必要等组合出来再从头算啊,如果前面的都一样,最后两位不一样,那岂不是浪费功夫,于是我就把判断也加到了递归里
cpp#include<iostream>
using namespace std;
int b[21]= {0},sum=0,book[4]= {0},sumn=0,bj[4]= {0,5,-10,2};
int k,d,a,n;
//简化过程
void dfs(int s) {
int t; //一个中间变量t,存储新加一个数据之前的总层数,不能是全局变量,只让它在本层递归起作用
if(s==n+1) { //同样的,到了总长度时就判断层数
if(sum==25) sumn++;
return;
}
for(int j=1; j<=3; j++) {
if(book[j]) {
b[s]=j;
book[j]--;
t=sum; //存储之前的层数
sum+=bj[j]; //新的数据改变层数
if(sum<0) sum=0; //一样的让它处于0到25
if(sum>25) sum=25;
dfs(s+1); //递归下一位
book[j]++; //还回来一个数据
sum=t; //总层数也还原
}
}
return;
}
//主函数
int main() {
cin>>k>>d>>a;
n=k+d+a;
book[1]=k;
book[2]=d;
book[3]=a;
dfs(1);
cout<<sumn;
return 0;
}
果然,快了一倍还多,可以打出GG了。
本文作者:KID
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!