[最短路,floyd] Codeforces 1202B You Are Given a Decimal String...

题目:http://codeforces.com/contest/1202/problem/B

B. You Are Given a Decimal String...
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Suppose you have a special xx-yy-counter. This counter can store some value as a decimal number; at first, the counter has value 00.

The counter performs the following algorithm: it prints its lowest digit and, after that, adds either xx or yy to its value. So all sequences this counter generates are starting from 00. For example, a 44-22-counter can act as follows:

  1. it prints 00, and adds 44 to its value, so the current value is 44, and the output is 00;
  2. it prints 44, and adds 44 to its value, so the current value is 88, and the output is 0404;
  3. it prints 88, and adds 44 to its value, so the current value is 1212, and the output is 048048;
  4. it prints 22, and adds 22 to its value, so the current value is 1414, and the output is 04820482;
  5. it prints 44, and adds 44 to its value, so the current value is 1818, and the output is 0482404824.

This is only one of the possible outputs; for example, the same counter could generate 02468024680240246802468024 as the output, if we chose to add 22during each step.

You wrote down a printed sequence from one of such xx-yy-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 ss — the remaining data of the sequence.

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

Input

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

Output

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

Example
input
Copy
0840
output
Copy
-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, 44-33-counter. One of the possible outcomes the counter could print is 0(4)8(1)4(7)00(4)8(1)4(7)0 (lost elements are in the brackets).

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

The 66-88-counter could print exactly the string 08400840.

题意:

有一个x-y计数器,tmp初始为0,计数器每次会输出tmp的最低位(也就是tmp%10),并会对tmp加上x或y,如此重复形成一个串
现在给你一个串s,询问x-y计数器x从0到9,y从0到9,在s中插入最少多少个数字使的当前串能由当前x-y计数器输出,否则如果没办法插入一些数字使得当前x-y计数器输出当前串则输出-1

思路:

若s串中每一个数字都代表一个状态,则问题就转化为上一个状态能否可达当前状态,如果可达最小代价是多少?所以我们需要知道0到9数字之间的转移代价
现在考虑如何状态如何转移,对于x-y计数器,当前数字是i,则i只能转移到(i+x)%10或(i+y)%10
接着考虑状态的最小代价,一个状态转移到另一个状态,其中可经过其他点,使得总距离缩小,如果不能经过其他来缩小距离则当前的两点距离就是最短距离
所以我们可以用floyd来求出任意两点距离,先考虑从0中转直到从9中转,注意中转点k要写在最外层,每次才能在上一个中转点最短路求出的基础上求这一个中转点的最短路
求出任意两点最短路后我们就可以判断是否可达,如果不可达返回-1,否则就累加答案,注意这里是插入多少点,也就是距离-1,这个-1是因为最后一个点是已经存在了

注意:

注意floyd的中转点k要写在最外层,每次才能在上一个中转点最短路求出的基础上求这一个中转点的最短路

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define fi s[i-1]-'0'
 4 #define se s[i]-'0'
 5 const int amn=2e6+5,inf=0x3f3f3f3f;
 6 char s[amn];
 7 int ans[15][15],dis[15][15];
 8 int solve(int x,int y,int len){
 9     memset(dis,inf,sizeof dis); ///x-y计数器必须要加x或加y,所以i==j时也赋值为inf
10     for(int i=0;i<=9;i++){
11         dis[i][(i+x)%10]=1;     ///现在考虑如何状态如何转移,对于x-y计数器,当前数字是i,则i只能转移到(i+x)%10或(i+y)%10
12         dis[i][(i+y)%10]=1;
13     }                           ///接着考虑状态的最小代价,一个状态转移到另一个状态,其中可经过其他点,使得总距离缩小,如果不能经过其他来缩小距离则当前的两点距离就是最短距离
14     for(int k=0;k<=9;k++)   ///floyd 的k要写在最外层,代表现在中转的节点k,下面求ij中转k的最短距离
15         for(int i=0;i<=9;i++)
16             for(int j=0;j<=9;j++)
17                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
18     int ans=0;
19     for(int i=1;i<len;i++){     ///求出任意两点最短路后我们就可以判断是否可达,如果不可达返回-1,否则就累加答案,注意这里是插入多少点,也就是距离-1,这个-1是因为最后一个点是已经存在了
20         if(dis[fi][se]==inf)return -1;
21         ans+=dis[fi][se]-1;
22     }
23     return ans;
24 }
25 int main(){
26     ios::sync_with_stdio(0);
27     cin>>s;
28     int len=strlen(s);
29     for(int i=0;i<=9;i++){
30         for(int j=0;j<=9;j++){
31             cout<<solve(i,j,len)<<(j<9?' ':'\n');
32         }
33     }
34 }
35 /**
36 有一个x-y计数器,tmp初始为0,计数器每次会输出tmp的最低位(也就是tmp%10),并会对tmp加上x或y,如此重复形成一个串
37 现在给你一个串s,询问x-y计数器x从0到9,y从0到9,在s中插入最少多少个数字使的当前串能由当前x-y计数器输出,否则如果没办法插入一些数字使得当前x-y计数器输出当前串则输出-1
38 若s串中每一个数字都代表一个状态,则问题就转化为上一个状态能否可达当前状态,如果可达最小代价是多少?所以我们需要知道0到9数字之间的转移代价
39 现在考虑如何状态如何转移,对于x-y计数器,当前数字是i,则i只能转移到(i+x)%10或(i+y)%10
40 接着考虑状态的最小代价,一个状态转移到另一个状态,其中可经过其他点,使得总距离缩小,如果不能经过其他来缩小距离则当前的两点距离就是最短距离
41 所以我们可以用floyd来求出任意两点距离,先考虑从0中转直到从9中转,注意中转点k要写在最外层,每次才能在上一个中转点最短路求出的基础上求这一个中转点的最短路
42 求出任意两点最短路后我们就可以判断是否可达,如果不可达返回-1,否则就累加答案,注意这里是插入多少点,也就是距离-1,这个-1是因为最后一个点是已经存在了
43 **/

 

posted @ 2019-08-28 11:29  Railgun000  阅读(252)  评论(0编辑  收藏  举报