A Polynomial-time Algorithm for the Change-Making Problem
David Pearson, A Polynomial-time Algorithm for the Change-Making Problem, Technical Report TR 94-1433, 1994.
コインの両替問題のインスタンスについて,貪欲法が常に最適解を返すかどうかをで判定する.更に,答えが"NO"の場合は,最適解と貪欲解が一致しない最小の反例を求めることができる.
色々な定義
仮定
n枚のコインの額面を正整数とする.更に,と仮定する(そうでなければ1を表現できない).
ベクトルによる表現
とする.
を表す各コインの枚数をとすると,
が成り立つ.
辞書式順序・包含関係
ベクトルと
に対して,辞書式順を以下で定義.
[tex:U
貪欲表現・極小表現
の貪欲表現を以下で定義.
:となるの中で辞書式順最大のもの
の極小表現を以下で定義.
:となるの中でが最小であるものの内,辞書式順最大のもの
が貪欲
が極小
コインシステムが正統
コインシステムが正統
補題1
(a)かつが貪欲が貪欲
(b)かつが極小が極小
証明は論文参照.
最小の反例の性質
が正統でないとする.をとなる最小の反例とする.
以下,
とする.
この時,との非ゼロのインデックス集合は互いに素.言い換えると,となるは存在しない.これは,補題1との最小性から背理法で証明可能.
:の最初の非ゼロのインデックス
:の最後の非ゼロのインデックス
とすると,以下の定理が成立する.
定理1
は以下で構成できる.
:に一致
:の対応する要素より1大きい
:0
証明は論文参照.
の候補は考えられるについて全パターン(通り)試せばよい.従って,以下のようにしてとを求めることが出来る.
Step.0
と初期化.
Step.1
iを2からnまで変化させる.
Step.2
jをiからnまで変化させる.
Step.3
を求める.
を構成する.
を求める.
を求める.
かつ[tex:w'
Step.4
iとjについて繰り返し.
適用可能な問題
AOJ 2069 Greedy, Greedy.
<2012/07/29追記>
Codeforces 10E Greedy Change([twitter:@iwiwi]さんに教えてもらいました.Thanks!!)
Javaによるサンプル
void checkCanonical(int[] c){ int n=c.length; sort(c); for(int i=0; i<n/2; i++){ int t=c[i]; c[i]=c[n-1-i]; c[n-1-i]=t; } int minW=-1; int[] minMw=null; for(int i=1; i<n; i++){ int x=c[i-1]-1; int[] gi=new int[n]; for(int k=0; k<n; k++){ gi[k]=x/c[k]; x%=c[k]; } for(int j=i; j<n; j++){ int[] mw=new int[n]; int mwSum=0; int w=0; for(int k=0; k<n; k++){ if(k<j) mw[k]=gi[k]; else if(k==j) mw[k]=gi[k]+1; else mw[k]=0; w+=mw[k]*c[k]; mwSum+=mw[k]; } int[] gw=new int[n]; int gwSum=0; int t=w; for(int k=0; k<n; k++){ gw[k]=t/c[k]; t%=c[k]; gwSum+=gw[k]; } if(mwSum<gwSum&&(minW==-1||w<minW)){ minW=w; minMw=mw.clone(); } } } // minW==-1ならcは正統 // そうでないなら,minWが最小の反例,minMwはminWの極小表現 }
戯言
面白いと思ったのが,特定のについて貪欲解が最適解かどうかを判定する問題がNP-hardであるにも関わらず,任意のについて成立するかを判定する問題がPに属するという事.定理1の証明が中々トリッキーで思いつかないなあと思った.実質4pageしかないので,読むのが楽だった.