私はこの問題を解決しています -
a、b、c で構成される文字列が与えられた場合、隣接する 2 つの異なる文字を取り、3 番目の文字に置き換えることができます。たとえば、「a」と「c」が隣接している場合、「b」に置き換えることができます。この操作を繰り返し適用して得られる最小の文字列は?
これで、次の再帰的ソリューションを作成しました (効率的とはほど遠い) が、それをトップダウンまたはボトムアップのソリューションに変換したいと考えています。
問題: メモ化のための表形式の構造を考え出すことができません。結果の文字列の長さだけを出力する必要がありますが、実際に問題を解決せずにどうすれば解決できますか。弦が少なくなってきましたが、保管方法は?
DPソリューションまたはメモ化のヒントは素晴らしいでしょう!
編集多くの人がトップダウンのメモ化ソリューションを思いついたので、ボトムアップも試してください。
#include <iostream>
#include <string>
using namespace std;
string reduce(string s)
{
if (s.length() <= 1)
return s;
int k;
char c = s[0];
string min = s;
for (k = 1; k < s.length() && c; ++k)
if (s[k] != c)
c = 0;
if (c)
return s;
if (s.length() == 2){
if (s[0] != 'a' && s[1] != 'a')
s[0] = 'a';
else if (s[0] != 'b' && s[1] != 'b')
s[0] = 'b';
else if (s[0] != 'c' && s[1] != 'c')
s[0] = 'c';
s.resize(1);
return s;
}
for (k = 1; k < s.length(); ++k){
string s1 = reduce(s.substr(0, k));
string s2 = reduce(s.substr(k));
if (s1.length() + s2.length() < min.length())
min = s1 + s2;
if (!s1.empty() && !s2.empty() && s1.back() != s2.front()){
if (s1.back() != 'a' && s2.front() != 'a')
s1.back() = 'a';
else if (s1.back() != 'b' && s2.front() != 'b')
s1.back() = 'b';
else if (s1.back() != 'c' && s2.front() != 'c')
s1.back() = 'c';
s1 = reduce(s1 + s2.substr(1));
if (s1.length() < min.length())
min = s1;
}
}
return min;
}
int main()
{
string input;
cin >> input;
cout << reduce(input) << endl;
return 0;
}