题目链接:http://codeforces.com/contest/1202/problem/B
题意:有一个由[0,9]的整数组成的序列,然后你有两种[0,9]的整数,对于序列S,要求你通过加上给定的两种整数中的一种并对10取余使得S0到S1,最后到Sn,求出这个步骤最少多少次。这只是题目的一个子问题,题目是给你一个序列,对于每一对(其中i,j都属于上文给定的范围),输出对应的次数,如果无法到达,则输出-1,按矩阵的形式输出答案,详情见代码。
思路:由于数字的范围很小,考虑爆搜得到答案,详情见代码。
代码:
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
using namespace std;
struct node
{
int x, step;
node(int _x,int _step) : x(_x), step(_step){}
};
string s;
int Time[10][10][10][10], vis[10]; //Time[x][y][i][j]表示用x,y两个数字使得i变为j的最小次数
void bfs(int x,int y,int s)
{
for(int i = 0; i < 10; ++i) vis[i] = 0;
queue <node> q;
node now(s,0);
q.push(now);
while(!q.empty()){
node t = q.front(); q.pop();
if(!vis[(t.x+x)%10]){
vis[(t.x+x)%10] = 1;
Time[x][y][s][(t.x+x)%10] = t.step+1;
q.push(node{(t.x+x)%10,t.step+1});
}
if(!vis[(t.x+y)%10]){
vis[(t.x+y)%10] = 1;
Time[x][y][s][(t.x+y)%10] = t.step+1;
q.push(node{(t.x+y)%10,t.step+1});
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
memset(Time,-1,sizeof Time);
for(int i = 0; i < 10; ++i)
for(int j = 0; j < 10; ++j) //存在对称性,可以节省时间,这里可以不弄
for(int k = 0; k < 10; ++k)
bfs(i,j,k);
cin>>s;
int len = s.length();
for(int i = 0; i < 10; ++i){
for(int j = 0; j < 10; ++j){
int ans = 0;
for(int k = 1; k < len; ++k){
if(Time[i][j][s[k-1]-'0'][s[k]-'0'] == -1){
ans = -1; break;
}
ans += Time[i][j][s[k-1]-'0'][s[k]-'0'];
}
if(ans == -1)
cout<<ans<<(j==9?'\n':' ');
else
cout<<ans-len+1<<(j==9?'\n':' ');//实际为插入的数字,但我们求的是变化的次数,因此减一
}
}
return 0;
}