codeforces 1202B. You Are Given a Decimal String... (最短路floyd)

B. You Are Given a Decimal String…

Suppose you have a special x-y-counter. This counter can store some value as a decimal number; at first, the counter has value 0.

The counter performs the following algorithm: it prints its lowest digit and, after that, adds either x or y to its value. So all sequences this counter generates are starting from 0. For example, a 4-2-counter can act as follows:

it prints 0, and adds 4 to its value, so the current value is 4, and the output is 0;
it prints 4, and adds 4 to its value, so the current value is 8, and the output is 04;
it prints 8, and adds 4 to its value, so the current value is 12, and the output is 048;
it prints 2, and adds 2 to its value, so the current value is 14, and the output is 0482;
it prints 4, and adds 4 to its value, so the current value is 18, and the output is 04824.
This is only one of the possible outputs; for example, the same counter could generate 0246802468024 as the output, if we chose to add 2 during each step.

You wrote down a printed sequence from one of such x-y-counters. But the sequence was corrupted and several elements from the sequence could be erased.

Now you’d like to recover data you’ve lost, but you don’t even know the type of the counter you used. You have a decimal string s — the remaining data of the sequence.

For all 0≤x,y<10, calculate the minimum number of digits you have to insert in the string s to make it a possible output of the x-y-counter. Note that you can’t change the order of digits in string s or erase any of them; only insertions are allowed.

Input

The first line contains a single string s (1≤|s|≤2⋅106, si∈{0−9}) — the remaining data you have. It’s guaranteed that s1=0.

Output

Print a 10×10 matrix, where the j-th integer (0-indexed) on the i-th line (0-indexed too) is equal to the minimum number of digits you have to insert in the string s to make it a possible output of the i-j-counter, or −1 if there is no way to do so.

Example
input

0840

output

-1 17 7 7 7 -1 2 17 2 7
17 17 7 5 5 5 2 7 2 7
7 7 7 4 3 7 1 7 2 5
7 5 4 7 3 3 2 5 2 3
7 5 3 3 7 7 1 7 2 7
-1 5 7 3 7 -1 2 9 2 7
2 2 1 2 1 2 2 2 0 1
17 7 7 5 7 9 2 17 2 3
2 2 2 2 2 2 0 2 2 2
7 7 5 3 7 7 1 3 2 7

Note

Let’s take, for example, 4-3-counter. One of the possible outcomes the counter could print is 0(4)8(1)4(7)0 (lost elements are in the brackets).

One of the possible outcomes a 2-3-counter could print is 0(35)8(1)4(7)0.

The 6-8-counter could print exactly the string 0840.

题意:

这题的题目其实还是看英文好懂,中文不太好讲明白:

题目定义 x - y - counter :是一个加法计数器。计数器数值初始为0,之后可以任意选择+x或者+y每次添加之后向数列中输出计数器数值的最后一个值

例如:4 - 2 - counter 进行+4 +4 +4 +4 +2 +4操作会生成数列 04824。
(
第一次加4时计数器末尾数值为0,数列加入0,计数器数值变为4
第二次加4时计数器末尾数值为4,数列加入4,计数器数值变为8
第三次加4时计数器末尾数值为8,数列加入8,计数器数值变为12
第四次加2时计数器末尾数值为2,数列加入2,计数器数值变为14
第五次加4时计数器末尾数值为4,数列加入4,计数器数值变为18
)
每步加x或加y是任意的。

给你一个残缺的数列(由0-9组成的字符串),问你0~9中全部两个数字生成这个包含这个子串的数列中间至少要插入多少数字才能补齐。以10 * 10矩阵格式输出,如果不存在输出-1。

例如:给定字符串:0840 用 4 - 3 - counter 生成 0(4)8(1)4(7)0是插入数字最少的数列,那么第四行第三列就是3。(表示3-4计数器生成这个数列至少要添加3个值)

分析:

有的人用dp解的
但是我觉得最短路更好理解而且更优,就不记录dp解法了

a加到b相当于一条有向边,权值为1(权值为操作次数)
跑一遍floyd求出i到j的最小操作次数
然后遍历数列,ans+=相邻两个数a到b的最小操作次数-1

看完思路直接看代码马上就能看懂的

code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<algorithm>
#include<sstream>
#define ll long long
#define s0(a) memset((a),0,sizeof(a))
//void fp(){freopen("1.txt","r",stdin);freopen("2.txt","w",stdout);}
const int inf=0x3f3f3f3f;
const int inn=-(1<<30);
using namespace std;
int n;
int g[10][10];
string s;
int ffind(int x,int y){
    memset(g,inf,sizeof g);//inf表示无法通过操作到达
    for(int i=0;i<10;i++){//可能到的地方操作次数为1
        g[i][(i+x)%10]=1;
        g[i][(i+y)%10]=1;
    }
    for(int k=0;k<10;k++){//floyd求a加b的最少操作次数
        for(int i=0;i<10;i++){
            for(int j=0;j<10;j++){
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
            }
        }
    }
    int ans=0;
    for(int i=0;i<n-1;i++){
        int aa=s[i]-'0';
        int bb=s[i+1]-'0';
        if(g[aa][bb]==inf){//无法到达返回-1
            return -1;
        }
        ans+=g[aa][bb]-1;
    }
    return ans;
}
int main(){
    cin>>s;
    n=s.size();
    for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            cout<<ffind(i,j)<<' ';
        }
        cout<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值