最小表示法------密码锁
P5941密码锁 | ||
|
问题描述
何老板有一把奇特的密码锁。
密码锁上有n个数字(范围0到9)排成一排。
密码锁上有两个按钮:
每按一次1号按钮,n个数字都会被加一(9加1变为0)
每按一次2号按钮,n个数字往右循环移一位。即i号数字移到i+1位置,原来n号数字移动到1号位置。
例如,密码锁上有数字5937,按一次1号按钮后,数字变为6048
再按一次2号按钮,数字变为8604
何老板这把锁的解锁密码是锁上能够得到的最小n位数,你能算出解锁密码吗?
输入格式
第一行,一个整数n,表示密码的位数
第二行,n个整数构成的数字串,表示密码锁初始数字
输出格式
一行,n个数字,表示解锁密码
样例输入 1
3
957
样例输出 1
024
样例说明:
按1号按钮得到:068
按1号按钮得到:179
按1号按钮得到:280
按1号按钮得到:391
按1号按钮得到:402
按2号按钮得到:240
按2号按钮得到:024
024是能够得到的最小的三位数了
样例输入 2
4
2014
样例输出 2
0142
样例输入 3
20
21347891785512126959
样例输出 3
00676714047689234623
提示
1 ≤ n ≤ 1000
来源 codeforces 496B
分析
2 号按钮的操作是把 n 个数字往右循环移动一位, 据此可以用最小表示法求出
在不按 1 号按钮的情况下能够得到的最小的 n 位数。
1 号按钮的操作是把每个数字加 1, 显然每个数字连续加 10 次后就会复原。 于
是可以对只按 1 号按钮能够得到的 10 种情况分别进行最小表示法, 然后找出
所有结果中字典序最小的即可。
在不按 1 号按钮的情况下能够得到的最小的 n 位数。
1 号按钮的操作是把每个数字加 1, 显然每个数字连续加 10 次后就会复原。 于
是可以对只按 1 号按钮能够得到的 10 种情况分别进行最小表示法, 然后找出
所有结果中字典序最小的即可。
#include<stdio.h> #include<bits/stdc++.h> using namespace std; string s,S,ans; int main() { int n; cin>>n; cin>>s; for (int i=0; i<=9; i++)//十次最小表示法 { S=s+s; int a=0,b=1; while (a<n&&b<n) { int k; for (k=0; k<n; k++) if (S[a+k]!=S[b+k])break; if (k==n) break; if (s[a+k]>s[b+k]) a=a+k+1; else b=b+k+1; if (a==b) b++; } s.clear(); for (int j=min(a,b); j<=n-1+min(a,b); j++) s+=S[j]; if (s<ans||i==0) ans.clear(),ans+=s; for (int j=0; j<s.size(); j++) { if (s[j]=='9') s[j]='0';//+1---9变0 else s[j]+=1; } } cout<<ans; }