NEUQ-ACM预备队-双周赛

7-1 输出全排列

在这里插入图片描述

思路

基本的DFS题目 使用数组存储全排列数 设置一个check数组检查对应数字是否使用过即可

代码

#include<iostream>
using namespace std;
int n;
int arr[10];
bool arrcheck[10];
//cnt 记录当前答案数组中存储了多少个数字,当存够n个以后就可以开始输出
void DFS(int cnt)
{
	if (cnt > n)
	{
		for (int i = 1; i <= n; i++)
		{
			printf("%d", arr[i]);
		}
		printf("\n");
		return;
	}
	for (int i = 1; i <= n; i++)
	{
		if (arrcheck[i])continue;
		arr[cnt] = i;
		arrcheck[i] = 1;
		DFS(cnt + 1);
		arrcheck[i] = 0;
	}
}
int main()
{
	cin >> n;
	DFS(1);
	return 0;
}

7-2 山

在这里插入图片描述

思路

我使用的是BFS,呃。。。因为山的状态和BFS的动态图里呈现的很相似,是水波式的

代码

#include<iostream>
#include<queue>
using namespace std;
const int N = 2005;
int m, n;
//本题是以山为基础,查询一个山向左向右向前向后是否还是山
int map[N][N];
bool mapcheck[N][N];
//前后左右捏
int detx[4] = { 0,1,0,-1 };
int dety[4] = { 1,0,-1,0 };
struct pos{
	int x, y;
};
int ans;
int main()
{
	cin >> m >> n;
	for (int i = 1; i <= m; i++)
		for (int j = 1; j <= n; j++)
			cin >> map[i][j];
	for(int i=1;i<=m;i++)
		for (int j = 1; j <= n; j++)
		{
			if (map[i][j] == 0 || mapcheck[i][j])continue;
			ans++;
			queue<pos> que;
			struct pos a;
			a.x = i; a.y = j;
			que.push(a);
			while (!que.empty())
			{
				a.x = que.front().x;
				a.y = que.front().y;
				que.pop();
				for (int k = 0; k < 4; k++)
				{
					struct pos to;
					 to.x = a.x + detx[k];
					 to.y = a.y + dety[k];
					if (map[to.x][to.y] == 1 && !mapcheck[to.x][to.y])
					{
						mapcheck[to.x][to.y] = 1;
						que.push(to);
					}
				}
			}
		}
	printf("%d", ans);
	return 0;
}

7-3 跳跃

在这里插入图片描述

思路

是比较简单的只有两个方向的DFS,同时同时!只要特别注意如果你经过一个点后,就不需要再走这个点了(在代码中。这个点往后的向左向右的情况已经全部涵盖了)在经过这点说明是重复了,会超时

代码

#include<iostream>
using namespace std;
const int N = 5 * 1e4;
int line[N];
bool linecheck[N];
int m, st;
bool ans;
void DFS(int index)
{
	if (ans == 1)return;
	if (line[index] == 0)
	{
		ans = 1;
		return;
	}
	int l = index - line[index];
	int r = index + line[index];
	if (ans == 1)return;
	if (l >= 0 && !linecheck[l])
	{
		linecheck[l] = 1;
			DFS(l);
	}

	if (ans == 1)return;
	if (r < m && !linecheck[r])
	{
		linecheck[r] = 1;
		DFS(r);
	}
		
	if (ans == 1)return;
}
int main()
{
	cin >> m;
	for (int i = 0; i < m; i++)
		cin >> line[i];
	cin >> st;
	linecheck[st] = 1;
	DFS(st);
	if (ans)printf("True");
	else printf("False");
	return 0;
}

7-4 最长光路

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路

这道题的难点有三点,一是处理镜子,二是判断环,三是合理存储数据。

由于初始方向是给定的,在不遇到镜子时不会改变(这点和地图式的DFS有很大差别),同时,存储数据时也是给初始的四个方向存储,在这里,使用类似EXCEL的绝对与相对引用的表达,我们需要一个绝对引用式的不改变的数字来表示初始的方向,以记录在U R D L四种方向的答案,同时,还需要一个相对引用式的可改变的数字作为真实的行走方向,于是出现了全局变量i和局部的target

至于判断环,则学习了一般的思路,如果一个点经过超过四次,则表明已经成环(对于一个点,不管如何走,在不成环的情况下应该至多有四次经过)此时,改变了一般的检查图,不需要检查这个点是否已经走过,只需要记录经过这个点的次数。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 500 + 5;
char Map[maxn][maxn];
int Mapcheck[505][505][4];
int sx, sy;
int n, m;
int ans[4] = { 1,1,1,1 };
//光上右下左
int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };
bool flag;
int i = 0;
void DFS(int tox, int toy, int target)
{
	Mapcheck[tox][toy][i]++;
	//成环
	if (Mapcheck[tox][toy][i] > 4)
	{
		flag = true;
		return;
	}
	//越过边界 表明光线射出
	if (tox<1 || tox>n || toy<1 || toy>m)
	{
		return;
	}
	//剩下的表明已经全部合法(不越界也没有成环)
	if (Map[tox][toy] == '.')
	{
		ans[i]++;
		DFS(tox + dx[target], toy + dy[target], target);
	}
	else if (Map[tox][toy] == 'C')
	{
		return;
	}
	else if (Map[tox][toy] == '/')
	{
		if (target == 0)			target = 1;
		else if (target == 1)		target = 0;
		else if (target == 2)		target = 3;
		else						target = 2;
		ans[i]++;
		DFS(tox + dx[target], toy + dy[target], target);
	}
	else if (Map[tox][toy] == '\\')
	{
		if (target == 0)			target = 3;
		else if (target == 1)		target = 2;
		else if (target == 2)		target = 1;
		else						target = 0;
		ans[i]++;
		DFS(tox + dx[target], toy + dy[target], target);
	}
	Mapcheck[tox][toy][i] = 0;
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cin >> Map[i][j];
		}
	}
	cin >> sx >> sy;
	for(int i=0;i<4;i++)
	Mapcheck[sx][sy][i] = 1;
	//int flag = false;
	for (i = 0; i < 4; i++)
	{
		int target = i;
		//记录是否走过
		DFS(sx + dx[i], sy + dy[i], target);
		if (flag)break;
	}
	if (flag)
	{
		if (i == 0)printf("U\nCOOL");
		else if (i == 1)printf("R\nCOOL");
		else if (i == 2)printf("D\nCOOL");
		else if (i == 3)printf("L\nCOOL");
	}
	else
	{
		int max = -1, ed = -1;
		for (i = 0; i < 4; i++)
		{
			if (max < ans[i])
			{
				max = ans[i];
				ed = i;
			}
		}
		i = ed;
		if (i == 0)printf("U\n%d", ans[i]);
		else if (i == 1)printf("R\n%d", ans[i]);
		else if (i == 2)printf("D\n%d", ans[i]);
		else if (i == 3)printf("L\n%d", ans[i]);
	}
	return 0;
}

7-5 回文数文回

在这里插入图片描述

思路

参考大犇们的代码和思路以后,挑选出这样的解题方式

通过取前五位数,并记录五位数的前四位数以还原原数字的办法(因为我们知道,1e9的数据是不会超过整型的)所以只需要还原数字,比较是否与给定数字小或相等即可

代码

#include<bits/stdc++.h>
using namespace std;
int n;
int ans;
int Ans(int n)
{
	//只取前四位 temp保存最终答案
	int temp = n;
	int arr[4]={0},i=0;
	n /= 10;//舍去第五位
	do
	{
		//取数并倒置存储
		arr[i++] = n % 10;
		n /= 10;
	} while (n != 0);
	for ( i = 0; i < 4; i++)
	{
		temp *= 10;
		temp += arr[i];
	}
	return temp;

}
int main()
{
	cin >> n;
	for (int i = 10000; i <= 99999; i++)
	{
		if (Ans(i) <= n)
		{
			ans++;
		}
	}
	printf("%d", ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值