[CSP-S 2023] 密码锁
題目描述
小 Y 有一把五個撥圈的密碼鎖。如圖所示,每個撥圈上是從 \(0\) 到 \(9\) 的數字。每個撥圈都是從 \(0\) 到 \(9\) 的循環,即 \(9\) 撥動一個位置后可以變成 \(0\) 或 \(8\),
因為校園里比較安全,小 Y 采用的鎖車方式是:從正確密碼開始,隨機轉動密碼鎖僅一次;每次都是以某個幅度僅轉動一個撥圈或者同時轉動兩個相鄰的撥圈。
當小 Y 選擇同時轉動兩個相鄰撥圈時,兩個撥圈轉動的幅度相同,即小 Y 可以將密碼鎖從 \(\tt{0\;0\;1\;1\;5}\) 轉成 \(\tt{1\;1\;1\;1\;5}\),但不會轉成 \(\tt{1\;2\;1\;1\;5}\)。
時間久了,小 Y 也擔心這么鎖車的安全性,所以小 Y 記下了自己鎖車后密碼鎖的 \(n\) 個狀態,注意這 \(n\) 個狀態都不是正確密碼。
為了檢驗這么鎖車的安全性,小 Y 有多少種可能的正確密碼,使得每個正確密碼都能夠按照他所采用的鎖車方式產生鎖車后密碼鎖的全部 \(n\) 個狀態。
輸入格式
輸入的第一行包含一個正整數 \(n\),表示鎖車后密碼鎖的狀態數。
接下來 \(n\) 行每行包含五個整數,表示一個密碼鎖的狀態。
輸出格式
輸出一行包含一個整數,表示密碼鎖的這 \(n\) 個狀態按照給定的鎖車方式能對應多少種正確密碼。
樣例 #1
樣例輸入 #1
1
0 0 1 1 5
樣例輸出 #1
81
提示
【樣例 1 解釋】
一共有 \(81\) 種可能的方案。
其中轉動一個撥圈的方案有 \(45\) 種,轉動兩個撥圈的方案有 \(36\) 種。
【數據范圍】
對于所有測試數據有:\(1 \leq n \leq 8\)。
| 測試點 | \(n\leq\) | 特殊性質 |
|---|---|---|
| \(1\sim 3\) | \(1\) | 無 |
| \(4\sim 5\) | \(2\) | 無 |
| \(6\sim 8\) | \(8\) | A |
| \(9\sim 10\) | \(8\) | 無 |
特殊性質 A:保證所有正確密碼都可以通過僅轉動一個撥圈得到測試數據給出的 \(n\) 個狀態。
題解
剛開始看到這個題,橙題,我應該能做,發現如果n等于1的時候,答案肯定是81,但是當n比較大的時候,不知道該怎么做了?一直在想,他有什么樣的性質才能這樣?
但是,我一直有個感覺,這個題可以搜索,為什么呢?因為最多有5位密碼,后來換了思路,我們搜索得到所有可能的狀態,依次判斷這種狀態是否能通過撥圈達到題目中說的狀態,這樣的時間復雜度是O(100000),判斷的時間復雜度為5n,所以最終的時間復雜是O(500000n)。
枚舉的代碼非常好寫,但是判斷的代碼不好寫,譬如。5 9會變成6 0,7 1,8 2,9 3,0 4,1 5,2 6,3 7,4 8共9種狀態,我們發現他們的差是一樣的,但是有個問題,9會變0,這個怎么處理?我最終的處理方法是判斷兩者之間的大小關系,如果發生變化,把小的數字加上10,從而保持原來的大小關系,代碼如下:
點擊查看代碼
#include <bits/stdc++.h>
using namespace std;
int n,a[15][15],ans;
int c[10];
bool check(){
for(int i=1;i<=n;i++){
bool b=true;//是否轉動過撥圈
int f;
for(int j=1;j<=5;j++){
if(c[j]==a[i][j]) continue;
else{
if(b==false)
return false;
if(c[j+1]!=a[i][j+1]&&j<=4){
if(c[j]<c[j+1]){
f=a[i][j+1];
if(a[i][j+1]<a[i][j]) f=a[i][j+1]+10;
if(f-a[i][j]!=c[j+1]-c[j]) return false;
j++;
b=false;
continue;
}
if(c[j+1]==c[j]){
if(a[i][j+1]!=a[i][j]) return false;
j++;
b=false;
continue;
}
if(c[j+1]<c[j]){
f=a[i][j];
if(a[i][j]<a[i][j+1]) f=a[i][j]+10;
if(f-a[i][j+1]!=c[j]-c[j+1]) return false;
j++;
b=false;
continue;
}
}
if((c[j+1]==a[i][j+1]&&j<=4)||j==5){
b=false;//已經轉動過一次撥圈
}
}
}
if(b==true) return false;
}
return true;
}
void dfs(int k){
if(k==6){
if(check()) {
ans++;
//for(int i=1;i<=5;i++) cout<<c[i]<<" ";
//cout<<endl;
}
return;
}
for(int i=0;i<=9;i++){
c[k]=i;
dfs(k+1);
c[k]=0;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=5;j++){
scanf("%d",&a[i][j]);
}
}
dfs(1);
cout<<ans<<endl;
return 0;
}
總結
以上是生活随笔為你收集整理的[CSP-S 2023] 密码锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ Qt开发:Charts折线图绘制
- 下一篇: 招商网站平台有哪些(化肥招商网站)