P9752 [CSP-S 2023] 密码锁 题解
这辈子没想到因为语文问题过不了 OI 题。
好好好,所以相同幅度为啥方向不能不同/ll/ll/ll。
数据范围只有 \(8\),考虑从 00000 至 99999 进行枚举,对于每种情况判断是否符合标准:
- 若有一位与目标不同,则一定可以满足标准。
- 若有两位与目标不同,判断是否相邻且转动格数相同(且转动方向必须一致),则满足标准;其余情况均否。
- 若有三位及以上与目标不同,则一定不能满足标准。
对于每种枚举出的情况,我们只需对于给定的 \(n\) 个标准依次进行判断,都满足即成立。
calc 和 check 都是线性的,所有情况在 \(10^5 \times n\) 范围内,最坏也就是 \(8 \times 10^5\),随便过。
#include<bits/stdc++.h>
#define Std_Maker lhm
#define ll long long
using namespace std;
const int N=11;
int n,a[N],b[N],c[N],d[N],e[N],ans;
int calc(int i,int a,int j,int b)
{
if(i<a) i+=10;
if(j<b) j+=10;
if((i-a)==(j-b)) return 1;
else return 0;
}
int check(int a,int b,int c,int d,int e,int i,int j,int k,int l,int p)
{
bool vis[N]={0};
int sam=0;
if(i==a) sam++,vis[1]=1;
if(j==b) sam++,vis[2]=1;
if(k==c) sam++,vis[3]=1;
if(l==d) sam++,vis[4]=1;
if(p==e) sam++,vis[5]=1;
if(sam<3 or sam==5) return 0;
if(sam==4) return 1;
if(vis[1]==0 and vis[2]==0) return calc(i,a,j,b);
else if(vis[2]==0 and vis[3]==0) return calc(k,c,j,b);
else if(vis[3]==0 and vis[4]==0) return calc(k,c,l,d);
else if(vis[4]==0 and vis[5]==0) return calc(p,e,l,d);
else return 0;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i]>>c[i]>>d[i]>>e[i];
for(int i=0;i<=9;i++)
{
for(int j=0;j<=9;j++)
{
for(int k=0;k<=9;k++)
{
for(int l=0;l<=9;l++)
{
for(int p=0;p<=9;p++)
{
bool pd=1;
for(int tar=1;tar<=n;tar++)
{
if(check(a[tar],b[tar],c[tar],d[tar],e[tar],i,j,k,l,p)==0)
{
pd=0;
break;
}
}
if(pd==1) ans++;
}
}
}
}
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号