暴力枚举
2025-10-29 22:56:45
发布于:北京
11阅读
0回复
0点赞
#include<bits/stdc++.h>
using namespace std;
int wrong[10][5]; //存储n个状态,每行5位密码状态
int n;
bool isans(int p[5],int s[5]){//枚举密码p,错误状态wrong
int diff[5],cnt=0;//diff存储每个位置的差值,cnt统计非零差值(不与原数相等的数)的个数
//计算每个位置的差值(处理模10循环)
for(int i=0;i<5;i++){//遍历5个拨圈
//计算s[i]与p[i]的差值,+10再%10确保结果在0-9之间(处理负数)
diff[i]=(s[i]-p[i]+10)%10;
//差值为9等于-1(因为9转动1格到0等于-1转动1格到0)
if(diff[i]==9)diff[i]=-1;
//统计非零差值的数量(有多少个拨圈转动)
if(diff[i]!=0)cnt++;
}
//情况1:单拨圈操作(仅1个拨圈转动,且幅度不为0(不为原数))
if(cnt==1){//只有1个非零差值
for(int i=0;i<5;i++){//遍历差值数组
//若该位置差值(diff[i])相同,说明符合单拨圈操作
if(diff[i]!=0)
return 1;//合法,返回true
}
return 0;//若唯一非零差值为0(为原数),不合法
}
//情况2:双相邻拨圈操作(2个相邻拨圈转动,幅度相同)
if(cnt==2){//只有2个非零差值
int pos[2],idx=0;// pos存储非零差值的位置,idx是位置数组的索引
//记录非零差值的位置(哪个拨圈转动)
for(int i=0;i<5;i++){
if(diff[i]!=0){
pos[idx++]=i;// 存储位置i
}
}
//检查条件是否满足:
if(pos[1]==pos[0]+1)//1.转动的拨圈位置相邻(pos[1]=pos[0]+1)
if(diff[pos[0]]==diff[pos[1]])//2.转动的拨圈差值相同(拨圈转动幅度相同)
if(diff[pos[0]]!=0)//3.差值相同(转动幅度合法)
return 1;
}
// 其他情况(非1或2个拨圈被转动):不合法
return false;
}
int main(){
freopen("lock.in","r",stdin);
freopen("lock.out","w",stdout);
cin>>n;
//n个状态
for(int i=0;i<n;i++){
for(int j=0;j<5;j++){
cin>>wrong[i][j];
}
}
int ans=0;
int p[5];//当前枚举密码
//枚举所有密码
for(p[0]=0;p[0]<10;p[0]++)//拨圈:0-9
for(p[1]=0;p[1]<10;p[1]++)
for(p[2]=0;p[2]<10;p[2]++)
for(p[3]=0;p[3]<10;p[3]++)
for(p[4]=0;p[4]<10;p[4]++){
bool ok=1;//标记
//检查该密码能否生成所有输入状态
for(int i=0;i<n;i++){
//若不能生成第i个状态,标记为无效并跳出循环
if(!isans(p,wrong[i])){
ok=0;
break;
}
}
//若能生成所有状态,有效密码数量+1
if(ok)ans++;
}
cout<<ans;//输出
fclose(stdin);
fclose(stdout);
return 0;
}
这里空空如也

有帮助,赞一个