第一周代码(队列杨辉 + BFS人狼菜羊)(递推+递归)

2023/10/9        周一

队列的应用:杨辉三角

queue.h文件:

//循环队列定义,队首指针和队尾指针
typedef struct
{
	ElemType queue[MaxQueueSize];
	int front;
    int rear; 
    int count;  //计数器
}Queue;

//初始化队列
void QueueInitiate(Queue *Q)
{
	Q->count = 0;
	Q->front = 0;
	Q->rear = 0;
}

//检查队列是否为空
int QueueNotEmpty(Queue Q)
{
	if(Q.count == 0)
		return 0;
	else
		return 1;
}

//入队
int QueueAppend(Queue *Q, ElemType x)
{
	if ( Q->count>0 && Q->rear == Q->front )  //检查是否申请成功
	{
		printf("队列已满无法插入!\n");
		return 0;
	}
	else
	{
		Q->queue[Q->rear] = x;
		Q->rear = ( Q->rear + 1 ) % MaxQueueSize;
		Q->count++;
		return 1;
	}
}

//出队
int QueueDelete(Queue *Q, ElemType *x)
{
	if (Q->count == 0)  //队列中只有一个节点
	{
		printf("循环队列已空!\n");
		return 0;
	}
	else
	{
		*x = Q->queue[Q->front];  
		Q->front = ( Q->front + 1 ) % MaxQueueSize;  
		Q->count--;
		return 1;
	}
}

int QueueGet(Queue *Q, ElemType *d)
{
	if (Q->count == 0)  //队列中只有一个节点
	{
		printf("循环队列已空!\n");
		return 0;
	}
	else
	{
		*d = Q->queue[Q->front]; 
		return 1;
	}
}

.c文件:

#include <stdio.h>

typedef int ElemType;
#define MaxQueueSize 8  //7的时候队列会满,虽然结果没问题
#include "queue.h"

int main()
{
	Queue q1;
	QueueInitiate(&q1);
	
	int i, j, x1, x2;
	int N = 8;
	QueueAppend(&q1, 1);  //先将1入队(第一行第一个)	
	for(i=1; i<N; i++)
	{
		x2 = 0;  //保证每行第一个数是1
		for(j=1; j<=i; j++)
		{
			QueueDelete(&q1, &x1);//出队,元素存在x1地址中
			printf("%d  ", x1);
			QueueAppend(&q1, x1+x2);//入队
			x2 = x1;
			if(j == i)
				QueueAppend( &q1, 1);//每一行最后一个为1
		}
		printf("\n");
	}
}

2023/10/10        周二

农夫过河问题

queue.h文件同上

Stack.h文件

//typedef int Elemtype;
typedef struct Stack
{
	ElemType stack[MaxSize];
	int top;  //栈顶下标值
}Stack;
//栈初始化
void StackInitiate(Stack *S)	
{
	S->top = 0;
}
//返回栈的大小
int StackSize(Stack S)
{
	return S.top;
}
//判断栈是否为空
int StackNotEmpty(Stack S)
{
	if(S.top <= 0) //空栈的情况
		return 0;
	else
		return 1;
}
//清空栈
void ClearStack(Stack *S)
{
	S->top = 0;
}
//入栈
int StackPush(Stack *S, ElemType x)
{
	if (S->top >= MaxSize)
	{
		printf("栈已满无法插入!\n");
		return 0;
	}
	else
	{
		S->stack[S->top] = x;
		S->top++;
		return 1;
	}
}
//出栈
int StackPop(Stack *S, ElemType *d)
{
	if(S->top <= 0)
	{
		printf("栈已空无数据元素出栈!\n");
		return 0;
	}
	else
	{
		S->top--;  //先减后弹出
		*d = S->stack[S->top];  //将栈顶元素值赋给*d
		return 1;
	}
}
//取栈顶元素
int StackTop(Stack S, ElemType *d)
{
	if(S.top <= 0)
	{
		printf("栈已空!\n");
		return 0;
	}
	else
	{
		*d = S.stack[S.top - 1];  //将栈顶元素值赋给*d
		return 1;
	}
}

.c文件:

#include <stdio.h>

typedef int ElemType;
#define MaxQueueSize 10
#define MaxSize 15
#include "queue.h"
#include "Stack.h" //栈用于输出

int farmer(int location) //判断农夫位置
{
	return (0 != (location & 0x08));
}

int wolf(int location) //判断狼位置
{
	return (0 != (location & 0x04));
}

int cabbage(int location) //判断白菜位置
{
	return (0 != (location & 0x02));
}

int goat(int location) //判断羊位置
{
	return (0 != (location & 0x01));
}

int safe(int location)
{
	//羊和白菜被单独留在同一岸边(左右岸都可以)
	if( (goat(location) == cabbage(location)) && (goat(location) != farmer(location)) )
		return 0;  //不安全
	//羊和狼被单独留在同一岸边(左右岸都可以)
	if( (goat(location) == wolf(location)) && (goat(location) != farmer(location)) )
		return 0;  //不安全
	return 1;
}

void bin_print(int num)
{
	char tmp[4];
	int i;
	for(i=0; i<4; i++)
	{
		tmp[i] = num & 0x01;
		num >>= 1;
	}
	for(i=3; i>=0; --i)
		putchar( (tmp[i] == 0) ? '0' : '1' );
	return;
}

int main()
{
	int i, movers, location, newlocation;
	int rount[16];
	for( i=0; i<16; i++)
		rount[i] = -1;
		
	Queue moveProcess;
	QueueInitiate(&moveProcess);
	QueueAppend(&moveProcess, 0x00);
	
	rount[0] = 0;
	//异常处理?
	while( QueueNotEmpty(moveProcess) && (rount[15] == -1) )
	{
		QueueGet(&moveProcess, &location);  //当前状态
		QueueDelete(&moveProcess, &location);	//考虑各种物品移动
		for(movers = 1; movers <= 8; movers <<= 1 )  
		{		
		//<<为左移操作符 左边丢弃一位,右边补0,011->110
		//农夫与移动的物品在同一侧
			if( (0 != ( location & 0x08 )) == (0 != ( location & movers ) ) )
			{
				newlocation = location ^ ( 0x08 | movers );  //计算新状态
				//新状态安全且未处理
				if( safe(newlocation) && ( rount[newlocation] == -1 ) )
				{
					rount[newlocation] = location;  //记录新状态的前驱
					QueueAppend(&moveProcess, newlocation);  //新状态进入队列
				}
			} 
		}		
	}
	printf("rount数组:");
	for( i=0; i<16; i++)
		printf("%d  ", rount[i]);
	printf("\n");
	
	if(rount[15] != -1)
	{
		printf("过河的状态转换步骤为:\n");		
		Stack s;
		StackInitiate(&s);
		for( location = 15; location >= 0; location = rount[location] )
		{
			StackPush(&s, location);//结果放入栈中
			if(location == 0)  //必要的终止条件
				break;
		}
		
		i=0;
		while(s.top != 0)//top指针判断终止
		{
			StackPop(&s, &location);
			printf("第%d步 ", i);
			i++;
			bin_print(location);
			printf("\n");
		}		
	}
	else
		printf("No solution.\n");
}

2023/10/11        周三

练习1 组合数


【问题描述】
从4个人中选2个人参加活动,一共有 6种选法。
从n个人中选m个人参加活动,一共有多少种选法?下面的函数实现了这个功能。
请仔细分析代码,填写缺少的部分(下画线部分)。


int f(int n, int m)
{
        if(m>n) return 0;
        if(m==0) ___;
        return f(n-1,m-1) + ____;
}
请仔细阅读分析源码,填写缺失部分的内容。

【题目分析】

在网上找到了这么个公式

按着这个公式写就行

上面一行m==0是用来计算运行到m=0需要几步,这几步其实就是选法

【参考答案】

return 1

f(n-1, m)

2023/10/12        周四

蓝桥杯练习2 李白打酒

【题目描述】

    话说大诗人李白,一生好饮。幸好他从不开车。

    一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

    无事街上走,提壶去打酒。
    逢店加一倍,遇花喝一斗。

    这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。 

    请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
【题目分析】

一开始想限制酒壶中酒的数量不超过8斗,但是通过这一点做不出什么出来。

方案数,多少种问题用dfs非常好用

【参考代码】

#include <iostream>
using namespace std;

int res;

int dfs(int num, int store, int flower, int flag)
{//不用flag结果为27,flag用于判断最后一步必须是花,酒才能喝完
	if (store == 0 && flower == 0 && num == 0 && flag == 0)
	{
		res++;
		return 0;
	}
	if (store > 0)  //遇到店装酒
		dfs(num * 2, store - 1, flower, -1);
	if (flower > 0 && num > 0)  //遇到花喝酒
		dfs(num - 1, store, flower - 1, 0);
}

int main()
{
	res = 0;
	dfs(2, 5, 10, -1);
	cout << res;
}

【运行结果】

14

2023/10/13        周五

蓝桥杯练习4 最大公约数

【输入样例】

6 9

【输出样例】

3

【参考代码】

#include <iostream>
using namespace std;

int main()
{
	int a, b, temp;
	cin >> a >> b;
	if (a < b)
	{
		temp = a;
		a = b;
		b = temp;
	}
	while (b != 0)
	{
		temp = a % b;  //temp=0即为已经找到最大公约数,所以b=0为判定条件
		a = b;
		b = temp;
		cout << b << endl;
	}
	cout << "最大公约数是:" << a;
}

2023/10/14-15        周六日

蓝桥杯练习5 带分数

【题目描述】
100 可以表示为带分数的形式:100=3+69258/714
还可以表示为:100=82+3546/197
注意特征:带分数中,数字 1∼9 分别出现且只出现一次(不包含 0)。
类似这样的带分数,100 有 11 种表示法。

【输入格式】
一个正整数N(N<1000*1000)。

【输出格式】
输出输入数字用数码 1∼9 不重复不遗漏地组成带分数表示的全部种数。

【题目分析】

本题思路和代码参考此大佬推文http://t.csdnimg.cn/elcTu

使用全排列+递归

注意判断条件,因为C++中除法是整除,所以要转化为加减乘来计算

【参考代码】

#include <iostream>
using namespace std;
const int N = 10;

int target; //输入的数
int num[N]; //保存全排列的结果
bool used[N]; //生成全排列过程中标记是否使用过
int cnt; //计数,最后输出的结果

//计算num数组中一段的数是多少
int calc(int l, int r) 
{
    int res = 0;
    for (int i = l; i <= r; i++)
        res = res * 10 + num[i];
    return res;
}

//生成全排列
//当全排列生成后进行分段
void dfs(int u) 
{
    //用两层循环分成三段
    if (u == 9)
    {
        for (int i = 0; i < 7; i++)
            for (int j = i + 1; j < 8; j++) 
            {
                int a = calc(0, i); //加号左边整数
                int b = calc(i + 1, j);
                int c = calc(j + 1, 8);
                //注意判断条件,因为C++中除法是整除,所以要转化为加减乘来计算
                if (a * c + b == c * target)
                {
                    cout << target <<" = " << a << "+" << b << "/" << c << endl;
                    cnt++;
                }            
            }
        return ;
    }
    //搜索模板
    for (int i = 1; i <= 9; i++)
    {
        if (!used[i])
        {
            used[i] = true; //标记使用
            num[u] = i;
            dfs(u + 1);
            used[i] = false; //还原现场
         }
    }   
}

int main() 
{
    cin >> target;
    dfs(0);
    printf("%d\n", cnt);
    return 0;
}

蓝桥杯练习3 组合数

【问题描述】

1~9组成三个3位数,每个数字恰好使用一次,要求3个数的比满足1:2:3,例如192 384 576。

【输入格式】

无数人

【输出格式】

输入T行,每行3个数,表示符合要求的三个三位数。

【样例输出】

192 384 576

...

【题目分析】

按照a:b:c=1:2:3的比例穷举所有数
将a,b,c的百位、十位、个位分别拆分储存到整形数组s[9]中;
判断数组s[9]有无重复数字、是否有数字0

【参考代码】

#include <stdio.h>

int main()
{
	int a, b, c;						//令三个数分别为a:b:c
	int i, j, s[9];
	for (a = 100; a < 333; a++)			//数值不能重复
	{
		b = 2 * a, c = 3 * a;			//计算b、c的值
		s[0] = a / 100; s[1] = a % 100 / 10; s[2] = a % 10;  //分离a的百位、十位、个位。下同
		s[3] = b / 100; s[4] = b % 100 / 10; s[5] = b % 10;
		s[6] = c / 100; s[7] = c % 100 / 10; s[8] = c % 10;

		for (i = 0; i < 8; i++)			//判断是否有重复数字(前一个数字和后面所有数字比较,如第1个和第2个至9个比较)、是否有数字0
		{
			for (j = i + 1; j < 9; j++)
				if (s[i] == s[j] || s[i] == 0 || s[j] == 0)
					break;
			if (j < 9) break;  //前面break已经终止一个循环,下面break再终止一次
		}
		if (i == 8 && j == 9)			//无重复数字、也无0
			printf("%d %d %d\n", a, b, c);
	}
	return 0;
}

【运行结果】

蓝桥杯练习6 八皇后问题(待补充)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值