最小表示法------密码锁

P5941密码锁
时间限制 : - MS   空间限制 : - KB 
评测说明 : 1s,128m
问题描述

何老板有一把奇特的密码锁。
密码锁上有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 种情况分别进行最小表示法, 然后找出
所有结果中字典序最小的即可。
 
#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;
}
原文地址:https://www.cnblogs.com/CXYscxy/p/11352616.html