C++で解く!チップ移動の最小コストを求めるアルゴリズム
いくつかのチップが与えられ、i番目のチップは現在、位置 chips[i] に置かれています。次の2種類の操作を、任意のチップに対して何度でも(0回でも可)実行できます。
- i番目のチップを左右どちらかの方向に2単位移動する(コスト0)
- i番目のチップを左右どちらかの方向に1単位移動する(コスト1)
すべてのチップを同じ位置に集めるために必要な最小コストを求めてください。最終的な位置はどこでも構いません。例えば、チップの初期配列が [2,2,2,3,3] の場合、出力は 2 になります。4番目と5番目のチップを位置2へ移動させる際にそれぞれコスト1がかかるため、合計の最小コストは 2 となります。
解法のアプローチ
この問題の鍵となるのは「偶奇性(パリティ)」です。2単位の移動はコスト0で行えるため、偶数位置にあるチップは他のどんな偶数位置へでも無料で移動できます。奇数位置のチップについても同様です。つまり、コストが発生するのは「偶数位置から奇数位置へ」、あるいはその逆の移動だけなのです。
そこで、以下の手順で解きます。
- odd := 0、even := 0 として初期化する
- 配列の先頭から末尾までループする
- chips[i] が奇数なら odd をインクリメントし、そうでなければ even をインクリメントする
- odd と even の小さい方を返す
C++の実装例
以下の実装を見ると、より理解が深まるでしょう。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int minCostToMoveChips(vector<int>& chips) {
int odd = 0;
int even = 0;
for(int i = 0; i < chips.size(); i++){
if(chips[i] & 1) odd++;
else even++;
}
return min(odd, even);
}
};
main(){
Solution ob;
vector<int> v1 = {2,2,2,3,3};
cout << ob.minCostToMoveChips(v1);
}入力
[2,2,2,3,3]
出力
2
-
C++で解く「最大水量コンテナ」問題 ― 二重ポインタでO(N)実装
問題概要 容器の壁の高さが配列として与えられ、その中で最大量の水を溜められる容器を見つけるのがこの問題の目標です。壁の高さは配列の要素で表され、2つの壁の間の距離(インデックスの差)が容器の幅として扱われます。たとえば、高さ Arr[i] と Arr[j] の壁の間の幅は j−i です(0 ≤ i < j ≤ N、N は壁の総数=配列の長さ)。 水位は低い方の壁の高さまでしか上がりません。Arr[i] < Arr[j] なら水位は Arr[i] となり、幅は j−i なので、溜められる水の面積は次の式で表せます。 面積 = min(Arr[i], Arr[j]) × (j − i)
-
C++で解く「3nスライスのピザ」問題 ― 動的計画法でスライスの合計を最大化する方法
問題の概要 大きさがまちまちの 3n 個のスライスからなるピザがあるとします。私と友人2人は、次のルールに従ってピザを取っていきます。 私が任意のスライスを1枚選びます。 友人のAmalは、私が選んだスライスの反時計回り方向に隣接するスライスを取ります。 友人のBimalは、私が選んだスライスの時計回り方向に隣接するスライスを取ります。 ピザのスライスがなくなるまで、この手順を繰り返します。 各スライスの大きさは、時計回りの順に並べた環状配列 slices として与えられます。求めるのは、私が手にできるスライスの大きさの合計の最大値です。 入出力例 入力が [9, 8, 6, 1, 1,