SRM 354 500pt : RemissiveSwaps
keyword
探索 C++
問題概要
N(<10^6)が与えられる。Nを10進表現したとき、0でない2つの桁を選んで、数字を1減らして交換する。この作業を任意回繰り替えしてできる最大の数を求める問題。
解法
桁数は増えないので到達可能な数はMAX_N以下。また、各数から到達可能な数の列挙はO((log N)^2)でできる。なのでDFSなりBFSなりで全ての到達可能なノードを調べられるので、最大のものを返せばよい。
感想
再帰関数でDFSしたけどスタックオーバーフローの可能性とか真面目に考えてなかった。結果的に大丈夫だったけど、可能ならやっぱり検証すべきだろう。
#include <string.h> #include <stdio.h> const int MAX_N = 10000009; bool visited[MAX_N]; int tens[20]; struct RemissiveSwaps { int findMaximum(int N) { tens[0] = 1; for(int i=1; i<20; i++){ tens[i] = tens[i-1]*10; } dfs(N); int ret = 0; for(int i=0; i<MAX_N; i++)if(visited[i]) ret = i; return ret; } void dfs(int n){ visited[n] = true; char buf[12]; sprintf(buf, "%d", n); int L = strlen(buf); for(int i=0; buf[i]; i++)if(buf[i] > '0'){ for(int j=i+1; buf[j]; j++)if(buf[j] > '0'){ int x = n + tens[L-i-1]*(buf[j] - buf[i] - 1) + tens[L-j-1]*(buf[i] - buf[j] - 1); if(!visited[x]){ dfs(x); } } } } };