2021.12.11吉首大学新生杯Problem C梅贾的窃魂卷

大一新生,刚看题目觉得不难,试图暴力枚举,结果失败,遂放弃,打完后才反应过来是搜索,于是又重写了一遍,记于此提醒自己。

分析题目,这就是个3种不同的小球不重复排列组合的题,于是我简化了一下,让k为1,d为2,a为3开始排列组合,每组合出一种结果判断是否25层,最后输出所有符合的个数,简简单单。

最开始套了个模板,结果超时了一点

#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;
}

 我一看,这个判断层数没必要等组合出来再从头算啊,如果前面的都一样,最后两位不一样,那岂不是浪费功夫,于是我就把判断也加到了递归里

#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了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值