P9752题解

题目传送门

思路

先说句题外话:原来提高组也有签到题!

都说了这是签到题,所以我们只需要纯暴力枚举 000009999900000\sim99999 的每个密码即可。这里的暴力枚举每个数可以是 DFS 枚举,也可以是直接五重循环枚举。

枚举好了以后,当然要进行判断这个密码是否合法了。是否合法必须满足这几个条件:

  1. 不能与任意一个锁车后的密码相同。
  2. 对于每个锁车后的密码,最多只能有 22 个不同之处。
  3. 如果这个锁车后的密码和当前枚举到的密码只有一个不同的数字,那枚举到的这个密码对于这个锁车后的密码就是合法的;如果有两个不同的数字,则需要判断,这两个不同的数字位置是否相邻,两个相差的值(需要转动的幅度)是否相同即可。

代码

# include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n, a[10][10], sum, b[10], tot, cha, last;
bool compare (int a[], int b[]) { //比较两个数组是否相等
	for (int i = 0; i < 5; ++ i)
		if (a[i] != b[i])
			return 0;
	return 1;
}
bool check () {
	for (int i = 0; i < n; ++ i)
		if (compare (a[i], b)) //如果有相等就不合法
			return 0;
	for (int i = 0; i < n; ++ i) {
		tot = cha = 0; //tot 表示不相等个数,cha 表示需要转动的幅度
		for (int j = 0; j < 5; ++ j)
			if (a[i][j] != b[j]) { //不相等!
				++ tot; //不相等个数加一
				if (tot > 2) //超过两个数不一样了,不合法
					return 0;
				if (! cha) //第一个不相等的数,不能根据之前的数判断是否合法
					cha = (a[i][j] - b[j] + 10) % 10; //计算需要转动的幅度
				else if ((a[i][j] - b[j] + 10) % 10 != cha || last != j - 1) //和上次需要转动的幅度不等,或与上次不相等的位置不相邻,则不合法
					return 0;
				last = j; //别忘了记录!
			}
	}
	return 1; //剩下就都合法了
}
void dfs (int step) { //普通 dfs,没必要讲吧
	if (step > 4) { //递归结束条件
		if (check ()) //判断是否合法
			++ sum;
		return ;
	}
	for (int i = 0; i < 10; ++ i)
		b[step] = i, dfs (step + 1);
	return ;
}
int main () {
	ios::sync_with_stdio (0);
	cin.tie (0);
	cout.tie (0);
	cin >> n;
	for (int i = 0; i < n; ++ i)
		for (int j = 0; j < 5; ++ j)
			cin >> a[i][j];
	dfs (0);
	cout << sum;
	return 0;
}
posted @   sz_jinzikai  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示