【SSLOJ1460】逛機房
阿新 • • 發佈:2020-08-11
題目
思路
考慮到可以特判 \(n=10^6\),這樣每個數就只有 6 位。可以考慮 bfs。
但是每次詢問都 bfs 一次複雜度顯然不對。發現目標狀態是一樣的,且 \(10^6\) 以內的完全平方數只有 \(10^3\) 個,所以可以從目標狀態開始搜尋,然後 \(O(1)\) 詢問。
那麼每次有兩種轉移方式:
- 將這個數字任意一位修改成任意一個數(注意不可以將最高位修改為 0)。
- 將一個位置前的數字全部向前移一位,然後在這個空出來的位置修改成任意數字。
時間複雜度 \(O(n+Q)\)。
程式碼
#pragma GCC optimize("Ofast") #pragma GCC optimize("inline") #include <bits/stdc++.h> using namespace std; const int N=1000010; int Q,n,dis[N]; bool vis[N]; struct node { int a[7]; }; queue<node> q; int get(node x) { int s=0; for (int i=1;i<=6;i++) s=s*10+x.a[i]; return s; } void bfs() { while (q.size()) { node u=q.front(); q.pop(); int len=1; while (len<6 && !u.a[len]) len++; for (int i=1;i<=6;i++) for (int j=0;j<=9;j++) { if (i==len && !j) continue; node v=u; v.a[i]=j; if (!dis[get(v)]) { dis[get(v)]=dis[get(u)]+1; q.push(v); } } if (len==1) continue; for (int i=len;i<=6;i++) { node v=u; for (int j=1;j<i;j++) v.a[j]=v.a[j+1]; for (int j=0;j<=9;j++) { v.a[i]=j; if (!dis[get(v)]) { dis[get(v)]=dis[get(u)]+1; q.push(v); } } } } } int main() { for (int i=1;i<1000;i++) { int p=i*i; node a; for (int j=6;j>=1;j--) a.a[j]=p%10,p/=10; q.push(a); dis[get(a)]=1; } bfs(); scanf("%d",&Q); while (Q--) { scanf("%d",&n); if (n==1000000) printf("0\n"); else printf("%d\n",dis[n]-1); } return 0; }