12.26日刷题总结

迷宫

题目描述

给定一个 N \times MN×M 方格的迷宫,迷宫里有 TT 处障碍,障碍处不可通过。

在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。

输入格式

第一行为三个正整数 N,M,TN,M,T,分别表示迷宫的长宽和障碍总数。

第二行为四个正整数 SX,SY,FX,FYSX,SY,FX,FY,SX,SYSX,SY 代表起点坐标,FX,FYFX,FY 代表终点坐标。

接下来 TT 行,每行两个正整数,表示障碍点的坐标。

输出格式

输出从起点坐标到终点坐标的方案总数。

输入输出样例

输入 #1复制

2 2 1
1 1 2 2
1 2

输出 #1复制

1

说明/提示

对于 100\%100% 的数据,1 \le N,M \le 51≤N,M≤5,1 \le T \le 101≤T≤10,1 \le SX,FX \le n1≤SX,FX≤n,1 \le SY,FY \le m1≤SY,FY≤m。

思路: 找迷宫的通关次数据比较小的时候,我们可以采用dfs(深度搜索)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int N,M,T,p,q,sum=0;
int book[6][6]={0},a[6][6]={0};
int dfs(int x,int y,int step)
{
	int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//走四个方向数组
	int tx,ty,k;
	if(x==p&&y==q)//到达终点的时候次数加1
	{
		sum++;
		return 0;//返回最近的dfs函数
	}
	for(k=0;k<4;k++)//四种走法的遍历
	{
		tx=x+next[k][0];
		ty=y+next[k][1];
		if(tx<1||ty<1||tx>N||ty>M)//判断是否越界
		continue;//此种走法越界了就另一种走法
		if(a[tx][ty]==0&&book[tx][ty]==0)//该位置不是障碍且没有走过的时候
		{
			book[tx][ty]=1;//标记这个点来过
			dfs(tx,ty,step+1);//调用dfs走下一步
			book[tx][ty]=0;//回溯
		}
	}	
	return sum;
}
int main()
{
	int sx,sy,t1,t2,ans=0;
	scanf("%d%d%d",&N,&M,&T);//N行M列T个障碍
	scanf("%d%d%d%d",&sx,&sy,&p,&q);//起点坐标和终点坐标的
	for(int i=0;i<T;i++)
	{
		scanf("%d%d",&t1,&t2);
		a[t1][t2]=1;//障碍为1
	}
	book[sx][sy]=1;//设置初始点来过
	ans=dfs(sx,sy,0);
	printf("%d",ans);
	return 0;
}
/*
0 1
0 0
*/

自然数的拆分问题

题目描述

任何一个大于 11 的自然数 nn,总可以拆分成若干个小于 nn 的自然数之和。现在给你一个自然数 nn,要求你求出 nn 的拆分成一些数字的和。每个拆分后的序列中的数字从小到大排序。然后你需要输出这些序列,其中字典序小的序列需要优先输出。

输入格式

输入:待拆分的自然数 nn。

输出格式

输出:若干数的加法式子。

输入输出样例

输入 #1复制

7

输出 #1复制

1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4

说明/提示

数据保证,1\le n\le 81≤n≤8。

思路:我们观察最后面几项总是前一个序列最后的数俩俩相加 ,因此我们采用dfs回溯出多种方案。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int n,a[9];
void print(int cnt)//(用于输出的函数)
{
	for(int i=0;i<cnt-1;i++)
	{
		printf("%d",a[i]);
		printf("+");
	}
	printf("%d",a[cnt-1]);
	puts("");
}
void dfs(int x,int sum,int cnt)//x为该数和的元素,sum为当前的的和,cnt用于数组存入数据的下标
{
	if(x==n)return ;//当x达到输入的数的时候不需要输出直接回到最近的dfs函数处
	if(sum==n)//总和达到输入的数字的时候
	{
		print(cnt);//调用输出函数输出存入a数组的数
		return ;
	}
	for(int i=x;i<=n-sum;i++)//此处需要注意的是i=x开始遍历而不是i=1(i=1会导致输出重复)(例如1 1 1 2 1和1 1 1 1 2)是一种情况
	{
		a[cnt]=i;//存入数组a
		dfs(i,sum+i,cnt+1);//调用dfs函数深度搜索直到总和达到输入的数字再逐步返回输出其他情况
	}
}
int main()
{
	scanf("%d",&n);
	dfs(1,0,0);
}
	

 PERKET

题目描述

Perket 是一种流行的美食。为了做好 Perket,厨师必须谨慎选择食材,以在保持传统风味的同时尽可能获得最全面的味道。你有 nn 种可支配的配料。对于每一种配料,我们知道它们各自的酸度 ss 和苦度 bb。当我们添加配料时,总的酸度为每一种配料的酸度总乘积;总的苦度为每一种配料的苦度的总和。

众所周知,美食应该做到口感适中,所以我们希望选取配料,以使得酸度和苦度的绝对差最小。

另外,我们必须添加至少一种配料,因为没有任何食物以水为配料的。

输入格式

第一行一个整数 nn,表示可供选用的食材种类数。

接下来 nn 行,每行 22 个整数 s_isi​ 和 b_ibi​,表示第 ii 种食材的酸度和苦度。

输出格式

一行一个整数,表示可能的总酸度和总苦度的最小绝对差。

输入输出样例

输入 #1复制

1
3 10

输出 #1复制

7

输入 #2复制

2
3 8
5 8

输出 #2复制

1

输入 #3复制

4
1 7
2 6
3 8
4 9

输出 #3复制

1

说明/提示

数据规模与约定

对于 100\%100% 的数据,有 1 \leq n \leq 101≤n≤10,且将所有可用食材全部使用产生的总酸度和总苦度小于 1 \times 10^91×109,酸度和苦度不同时为 11 和 00。

说明

附件下载

contest2_tasks.pdf101.88KB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct food
{
	int s;//酸度
	int k;//苦度
}a[11];
int n,min=1000000001,book[11]={0};//book数组用于记录是否加过该种调料
void dfs(int x,int y,int step)//step用于计录加了多少种调料
{
	if(step==n+1)return ;//此时所有调料都加了一遍则返回
	for(int i=1;i<=n;i++)//从第一种调料开始
	{
		if(book[i]==0)//没有加过的调料
		{
			book[i]=1;//设置为加过
			x*=a[i].s;//计算总酸度
			y+=a[i].k;//计算总苦度
			if(abs(x-y)<min)//酸度和苦度的差值若小于min则更新min的值
			{
				min=abs(x-y);
			}
			dfs(x,y,step+1);
			book[i]=0;//撤回这种调料
			x/=a[i].s;
			y-=a[i].k;
		}
	}
	return ;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d %d",&a[i].s,&a[i].k);
	}
	dfs(1,0,0);//此处的调用需要1 0 0,而不是0 0 0 (因为酸度是相乘)
	printf("%d",min);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡卡卡卡罗特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值