SRM 385 250pt: UnderscoreJustification
問題概要
単語が複数与えられる。単語の間にアンダースコアを入れて連結した長さをある値ぴったりにしたい。各単語間にはさまれるアンダースコアの長さの差が高々1になるようにするとき、辞書順最小のものを求める問題。
考えたこと
- 辞書順最小と言えばgreedy。
- アンダースコアの総数はすぐに計算できて、最低何文字いれないといけないかはすぐに分かる。
- 後は余ったものをどこに付けるか考えれば良い。
- 選択の余地がある時に、辞書順でgreedyに選んでやる。
practiceで通ったコード
#include <cctype> #include <vector> #include <string> using namespace std; struct UnderscoreJustification { string justifyLine(vector <string> words, int width) { int total = 0, N = words.size(); for(int i=0; i<N; i++){ total += words[i].length(); } //余分に使える数と最小数 int must = (width - total)/(N-1); int res = (width - total)%(N-1); //解を構成する string ret = words[0]; for(int i=1; i<N; i++){ int add = 0; if(res > (N - 1) - i || (res > 0 && islower(words[i][0])) ){ add++; res--; } ret += string(must + add, '_') + words[i]; } return ret; } };