C++题解 编程 洛谷 C++ 题解 洛谷P9752 [CSP-S 2023] 密码锁 题解 Jerry Zhou 2023-10-21 2024-11-18 读题点这里
题意简述
小 Y 拥有一个五个拨圈的密码锁,每个拨圈上标有数字 0 0 0 到 9 9 9 。每个拨圈都可以从 0 0 0 到 9 9 9 循环。小 Y 采用一种锁车方式:从正确密码开始,随机转动密码锁一次,每次只能以某个幅度转动一个拨圈或者同时转动两个相邻的拨圈。现在小 Y 记下了 n n n 个状态,这些状态都不是正确密码。要求找出有多少种可能的正确密码,使得每个正确密码都能按照小 Y 的锁车方式产生这 n n n 个状态。
思路分析
给定 n n n 个状态,我们要找到能产生这些状态的所有可能的正确密码数量。
首先,当 n = 1 n=1 n = 1 时,任意一个密码都能满足条件。因为无论哪个密码,只要按照给定的锁车方式进行一次操作,都能得到这个状态。所以,当 n = 1 n=1 n = 1 时,答案是 81 81 8 1 。
接下来考虑 n > 1 n>1 n > 1 的情况:
枚举所有可能的正确密码 :对于每一个错误状态,我们分别枚举单个拨圈和相邻两个拨圈的所有可能的转动情况,并将其保存在 pass
中。
判断当前密码能否通过所有的错误密码锁状态转动得到 :对于每一个可能的正确密码,我们检查是否能通过所有的错误密码锁状态转动得到。如果能够得到,就将计数器 cnt
增加。 cnt
就是最终的答案。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include <bits/stdc++.h> using namespace std;int n,cnt=0 ;string tmp,locks[11 ]; set<string> pass[11 ]; int main () { cin>>n; if (n==1 ){ cout<<81 <<endl; return 0 ; } for (int i=1 ;i<=n;i++){ for (int j=1 ;j<=5 ;j++){ int a; cin>>a; locks[i]+=(char )(a+'0' ); } } for (int i=1 ;i<=n;i++){ for (int j=0 ;j<5 ;j++){ for (int k=0 ;k<=9 ;k++){ if (locks[i][j]-'0' !=k){ tmp=locks[i].substr (0 ,j)+(char )(k+'0' )+locks[i].substr (j+1 ); pass[i].insert (tmp); } } } for (int j=0 ;j<4 ;j++){ for (int k=1 ;k<=9 ;k++){ char k1=locks[i][j]+k,k2=locks[i][j+1 ]+k; if (locks[i][j]+k>'9' ) k1=locks[i][j]+k-10 ; if (locks[i][j+1 ]+k>'9' ) k2=locks[i][j+1 ]+k-10 ; tmp=locks[i].substr (0 ,j)+k1+k2+locks[i].substr (j+2 ); pass[i].insert (tmp); } } } for (string i:pass[1 ]){ bool flag=true ; for (int j=2 ;j<=n;j++){ if (pass[j].find (i)==pass[j].end ()){ flag=false ; break ; } } if (flag) cnt++; } cout<<cnt<<endl; return 0 ; }