蓝桥杯 | 递归 2/25

时间:2021/2/25

测试练习

龟兔赛跑预测(蓝桥杯 基础练习)

问题描述
  兔子在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。
  只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。
输入格式
  输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2<=100;t<=300;s<=10;l<=10000且为v1,v2的公倍数)
输出格式
  输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。
  第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。
样例输入
10 5 5 2 20
样例输出
D
4
样例输入
10 5 5 1 20
样例输出
R
3
样例输入
10 5 5 3 20
样例输出
T
4

memset

//first
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N = 10010;
int tor, rab;
int rab_s[N];
int q;

int main(){
	int  v1, v2, t, s, l;
	cin >> v1 >> v2 >> t >> s >> l;
	tor = l / v2;//乌龟用时
	for(int ss = 1; ss <= tor; ss ++ ){
		rab = ss;
		if(rab_s[ss] == -1)  continue;
		q += v1;
		
		rab_s[ss] = q;
		if(q >= l)
			break;
			
		
		if(rab_s[ss] >= ss * v2 + t)
		    //memset(rab_s + ss + 1, -1, sizeof s);
		    for(int j = 1; j <= s; j ++ )
		        rab_s[ss + j] = -1;
		        
	}

    if(rab == tor && rab_s[rab] >= l)  printf("D\n%d\n", rab);
    else if(rab == tor && rab_s[tor] < l)  printf("T\n%d\n", tor);
    else printf("R\n%d\n", rab);
	return 0;
}

视频学习

蓝桥杯算法教学与培训 2.经典的递归问题(1)

组合问题递归
全排列
最大公共子序列

带分数(AcWing)

100 可以表示为带分数的形式:100 = 3 + 69258 / 714
还可以表示为:100 = 82 + 3546 / 197
注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。
类似这样的带分数,100 有 11 种表示法。
输入格式
一个正整数。
输出格式
输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。
数据范围
1≤N<106
输入样例1:
100
输出样例1:
11
输入样例2:
105
输出样例2:
6

n = a + b / c

  • a 从 1 到 9 枚举:当 a 是 1位数,2位数 ··· 时所有的全排列
    由于a < n < 1 0 6 10^{6} 106 , 所以 a 最多取到 6位数
  • a 的每个排列结果对应 c 在1~9剩下的数中取 1位数,2位数 ··· 时的所有全排列
  • 根据 b = n * c - a * c , 判断选出的 b 是否与 a c 共同用了1~9且只用一次:
    1.判断b是否含有 0 ,是否含有与a c 重复的数,自身是否含有重复的数
    2.判断a b c 是否用了0 ~ 9 所有的数

需注意的问题:
a b c 都不能为 0

#include <iostream>
#include <cstdio>
#include <cstring> 
using namespace std;

const int N = 10;
bool st[N], back[N];
int res;
int n;

bool check(int a, int c){
	long long b = n * (long long)c - a * c;
	if(!a || !b || !c)  return false;
	
	memcpy(back, st, sizeof st);
	while(b){
		int x = b % 10;//b 最后一位 
		b /= 10;
		if(!x || back[x])  return false;
		back[x] = true;
	}
	
	for(int i = 1; i <= 9; i ++ )
	    if(!back[i])
	        return false;
	
	return true;
}

void dfs_c(int s, int a, int c){
	if(s > 9)  return;
	
	if(check(a, c))  res ++;
	
	for(int i = 1; i <= 9; i ++ )
	    if(!st[i]){
	    	st[i] = true;
	    	dfs_c(s + 1, a, c * 10 + i);
	    	st[i] = false;
		}
}

void dfs_a(int s, int a){//s 表示已经选了多少个数 
	if(a >= n) return;//a 一定不会超过 n, a 的位数不会超过 6 
	if(a)  dfs_c(s, a, 0);

	for(int i = 1; i <= 9; i ++ )
		if(!st[i]){
			st[i] = true;
			dfs_a(s + 1, a * 10 + i);
			st[i] = false;
		}
	
}
int main(){
	cin >> n;
	dfs_a(0, 0);
	cout << res << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值