P9752题解
思路
先说句题外话:原来提高组也有签到题!
都说了这是签到题,所以我们只需要纯暴力枚举 的每个密码即可。这里的暴力枚举每个数可以是 DFS 枚举,也可以是直接五重循环枚举。
枚举好了以后,当然要进行判断这个密码是否合法了。是否合法必须满足这几个条件:
- 不能与任意一个锁车后的密码相同。
- 对于每个锁车后的密码,最多只能有 个不同之处。
- 如果这个锁车后的密码和当前枚举到的密码只有一个不同的数字,那枚举到的这个密码对于这个锁车后的密码就是合法的;如果有两个不同的数字,则需要判断,这两个不同的数字位置是否相邻,两个相差的值(需要转动的幅度)是否相同即可。
代码
# 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现