SRM572 DIV2 -Level2

<問題>
①2つの文字列が与えられる。
②それぞれの文字は、1回につきprevCostで前の文字に変えることができる。(aを除く)
③それぞれの文字は、1回につきnextCostで次の文字に変えることができる。(zを除く)
④このとき、最初の文字列から2つ目の文字列に変換するのにかかる最小のコストを返す。ただし、いつでも文字列中に同じ文字が存在してはならない。変えることができない場合はー1を返す。

<解き方>
シミュレーションを全探索で考えるのは難しいので効率のよい探索を考える。
まず、同じ文字が存在するかしないかは、2つの文字を相対的に見ればよい。
次に、どのケースのとき同じ文字列が存在するかを考える。
①2つが同じ順番のとき
 (小さい文字から大きい文字に変換)
 startが比較対象のstartより大きいかつ、goalが比較対象のgoalより小さいとNG
 (大きい文字から小さい文字に変換)
 startが比較対象のstartより小さいかつ、goalが比較対象のgoalより大きいとNG
②逆の順番のとき
 startが比較対象の文字より小さいかつ、goalが比較対象のgoalより大きいとNG
 もしくは
 startが比較対象の文字より大きいかつ、goalが比較対象のgoalより小さいとNG
 (より、と書きましたが=も含みます)

上記でもOKですが、
2つの文字の比較は上下が変わっても相対的に見れば同じことがわかれば
まとめることができます。
つまり、(start[i]-start[j])*(goal[i]-goal[j])<=0のときは-1を返してやればいいです。

あとはコストは常に移動の最小となるので、同じ文字が存在するときはー1、そうでなければ移動の最小コストを返してあげればOKです。

<コード>
class NextOrPrev {
public: int getMinimum(int nextCost, int prevCost, string start, string goal) {
int ans=0;
int n=start.size();
FORE(i,0,n){
if(start[i]==goal[i])continue;
if(start[i]<goal[i])ans+=(abs(start[i]-goal[i])*nextCost);
else ans+=(abs(start[i]-goal[i])*prevCost);
}
FORE(i,0,n)FORE(j,i+1,n)if((start[i]-start[j])*(goal[i]-goal[j])<=0)return -1;
return ans;
}
};



このエントリーをはてなブックマークに追加