编程之美2.8节。大略看了一下作者的解答。作者的解法有点动态规划的套路。这里尝试用广搜的办法来求解。在我们做乘法时,最低位的数字决定于乘数的最低位,而与乘数的高位无关。广搜的策略就是从低到高逐位尝试,直到找到结果。注意下面的代码中vis数组的使用。这个数组可以使广搜树得到有效剪枝。本来STL中vector<bool>的特化是被很多人批评的一件事,这里却恰是我想要的结果,不仅速度快,还可以有效节省空间。
struct
Item {
int v;
string s;
Item( int vv, const string & ss): v(vv), s(ss) {}
};
bool bfs( int v, string & s) {
while ( ! (v % 10 )) v /= 10 ;
vector < bool > vis(v, false );
queue < Item > q;
for ( int i = 1 ; i <= 9 ; ++ i) {
int p = v * i;
if (p % 10 <= 1 )
q.push(Item(p / 10 , string () + ( char )(i + ' 0 ' )));
}
while ( ! q.empty()) {
Item item = q.front();
q.pop();
if ( ! item.v) {
s = item.s;
break ;
}
if (vis[item.v]) continue ;
vis[item.v] = true ;
if (item.v % 10 <= 1 )
q.push(Item(item.v / 10 , item.s + ' 0 ' ));
for ( int i = 1 ; i <= 9 ; ++ i) {
int p = v * i + item.v;
if (p % 10 <= 1 )
q.push(Item(p / 10 , item.s + ( char )(i + ' 0 ' )));
}
}
size_t len = s.length();
for (; len > 0 && s[len - 1 ] == ' 0 ' ; -- len);
s.resize(len, 0 );
reverse(s.begin(), s.end());
return ! s.empty();
}
int main() {
int v;
while (cin >> v) {
string s;
bfs(v, s);
cout << s << ' \n ' ;
}
return 0 ;
}
int v;
string s;
Item( int vv, const string & ss): v(vv), s(ss) {}
};
bool bfs( int v, string & s) {
while ( ! (v % 10 )) v /= 10 ;
vector < bool > vis(v, false );
queue < Item > q;
for ( int i = 1 ; i <= 9 ; ++ i) {
int p = v * i;
if (p % 10 <= 1 )
q.push(Item(p / 10 , string () + ( char )(i + ' 0 ' )));
}
while ( ! q.empty()) {
Item item = q.front();
q.pop();
if ( ! item.v) {
s = item.s;
break ;
}
if (vis[item.v]) continue ;
vis[item.v] = true ;
if (item.v % 10 <= 1 )
q.push(Item(item.v / 10 , item.s + ' 0 ' ));
for ( int i = 1 ; i <= 9 ; ++ i) {
int p = v * i + item.v;
if (p % 10 <= 1 )
q.push(Item(p / 10 , item.s + ( char )(i + ' 0 ' )));
}
}
size_t len = s.length();
for (; len > 0 && s[len - 1 ] == ' 0 ' ; -- len);
s.resize(len, 0 );
reverse(s.begin(), s.end());
return ! s.empty();
}
int main() {
int v;
while (cin >> v) {
string s;
bfs(v, s);
cout << s << ' \n ' ;
}
return 0 ;
}