トップページに戻る
次のC++のサンプルへ
前のC++のサンプルへ
Problem76 100の分割数の数を求める
問題
5は数の和として6通りに書くことができる:
4 + 1
3 + 2
3 + 1 + 1
2 + 2 + 1
2 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1
2つ以上の正整数の和としての100の表し方は何通りか.
ソース
#include <string>
#include <Windows.h>
//const int TargetVal = 5;
const int TargetVal = 100;
struct JyoutaiDef
{
int Val;
int SumVal;
//std::string Keiro;
};
class CStack
{
private:
JyoutaiDef JyoutaiDefArr[100+1];
int ArrP;
public:
CStack(){ArrP=-1;};
int GetCount(){return ArrP+1;};
void Push(JyoutaiDef& pJyoutai);
JyoutaiDef Pop();
};
void CStack::Push(JyoutaiDef& pJyoutai)
{
const int UB = sizeof(JyoutaiDefArr)/sizeof(JyoutaiDef);
if(ArrP+1 > UB) puts("スタックのサイズ上限を超えました");
else JyoutaiDefArr[++ArrP] = pJyoutai;
}
JyoutaiDef CStack::Pop()
{
return JyoutaiDefArr[ArrP--];
}
void main()
{
CStack Stack;
JyoutaiDef WillPush;
for (int I = 1; I <= TargetVal/2; I++) { //和の半分までループ
WillPush.Val = I;
WillPush.SumVal = I;
//char wkCharArr[100];wsprintf(wkCharArr,"%d",I);
//WillPush.Keiro = wkCharArr;
Stack.Push(WillPush);
}
int AnsCnt = 0;
while (Stack.GetCount() > 0){
JyoutaiDef Popped = Stack.Pop();
if (Popped.SumVal == TargetVal) {
AnsCnt++;
//printf("%d個目の組み合わせ%s\n",AnsCnt, Popped.Keiro.c_str());
if(AnsCnt % 5000000 == 0) printf("%09d個目の組み合わせを発見。\n",AnsCnt);
continue;
}
for (int I = Popped.Val; I <= TargetVal - 1; I++) {
WillPush.Val = I;
WillPush.SumVal = Popped.SumVal + I;
//WillPush.Keiro = Popped.Keiro + "+";
//char wkCharArr[100];wsprintf(wkCharArr,"%d",I);
//WillPush.Keiro += wkCharArr;
if (WillPush.SumVal <= TargetVal) Stack.Push(WillPush);
else break;
}
}
printf("Answer=%d\n",AnsCnt);
}
実行結果
省略
150000000個目の組み合わせを発見。
155000000個目の組み合わせを発見。
160000000個目の組み合わせを発見。
165000000個目の組み合わせを発見。
170000000個目の組み合わせを発見。
175000000個目の組み合わせを発見。
180000000個目の組み合わせを発見。
185000000個目の組み合わせを発見。
190000000個目の組み合わせを発見。
Answer=190569291
解説
深さ優先探索で全探索してます。
STLのStackはDebugビルドだと遅いので、
ビルトイン配列でStackのデータ構造を実装してます。