トリッキーなプログラムの問題をしているところの良さを知ってもらい、私の頭の周辺

StackOverflow https://stackoverflow.com/questions/2320138

質問

まずは、ということを発見しましこの課題(I am Aレベルの学生など近い問題を解決す 方法 硬くもりの問題をずっと聴いていたい。suss改善プログラミング論理です。

と思ったシナリオが配列のランダムな整数、例えば10の整数です。ユーザー入力多い数のアルゴリズムのようどのような動作するように、番号にするため必要と認められる。例えば、作りたいと思ったのは和44からこの配列の整数:

myIntegers = array(1, 5, 9, 3, 7, 12, 36, 22, 19, 63);

を出力することはできない。

36 + 3 + 5 = 44

なされるようになっています。いく自分に明らかでない。として追加ボーナスをしてみたいと思いるアルゴリズムにおけ少なくして、数に限が必要ですので、和、または、エラーの場合の和できないときは、番号を供給します。

思いを繰返し、繰り返し処理の配列を数えるまでの和が満たされていた。んありがとうございますの頭の周りには何をすればいいのアルゴリズムを超過する和の必要性を選択的に何の数字から選択するための配列です。

んなの完了コード、または完全なアルゴリズムさんのご意見をどう進めることも有数のヒントか何かにする。私が開始されるであろうことはない。P

しかし、宿題も出されたりする。だけど何かをしたいというのが少します。

感謝のお役に立てるようだができます。:)

役に立ちましたか?

解決

あなたはを見ています ナップサックの問題

ナップサックの問題またはリュックサックの問題は、組み合わせの最適化における問題です。それぞれのアイテムのセットがあり、それぞれが重量と値を持つことで、各アイテムの数をコレクションに含めるために、合計重量が特定の制限よりも少なく、合計値はできるだけ大きいです。それは、固定サイズのナップサックに制約されており、最も有用なアイテムを埋める必要がある人が直面している問題からその名前を導き出します。


編集:あなたの特別なケースはです サブセット合計問題

他のヒント

意思 サブセット合計 行う? ;

これは古典です ナップザック 大学レベルのアルゴリズムコースで表示される問題(または、少なくとも私はそれを見ました)。これを紙で作業するのが最善であり、コード内のソリューションは比較的簡単に解決するのが必要です。

編集:考慮すべきことの1つはです 動的プログラミング.

あなたの問題はに関連しています サブセット合計問題。最悪の場合、すべての可能な組み合わせを試す必要があります。

ここにショートカットはありません。他の人が言ったことに加えて、これがどのような特定の問題であるかについて、ここにあなたに出発点を提供するためのいくつかの実用的なアドバイスがあります:

配列を並べ替えて、入力合計が与えられます m, 、アレイの最初の数字がより少ないことを見つけるでしょう m, 、 あれを呼べ n (これは合計の最初の可能な数値です)、そして可能な限り最高の補体から開始します(m-n)、あなたのやり方で働きます。

正確な一致が見つからない場合は、利用可能な最高のマッチを選択してください。 o, 、(今はあなたの2番目の数字です)、からの3番目の数字を探します(m-n-o)そして、再びあなたの道を歩みます。

正確な一致が見つからない場合は、次の番号n(インデックス1での元のnのインデックス)から始めて、同じことをします。 2つの数字の正確な一致が見つかるまで、これを続けることができます。 2つの数値で合計と一致しない場合は、プロセスを再度開始しますが、3番目の数字を含めるように展開します。等々。

それは再帰的に行うことができます。少なくともこのアプローチにより、一致を見つけたときに、セットの最小数の数字が合計入力合計を形成することが保証されます。

しかし、潜在的に、最悪の場合、あなたは全体をたくさん通過することになります。

編集: :Venrが正しく指摘しているように、私の最初のアプローチは間違っていました。これを反映するための編集アプローチ。

この問題には非常に効率的なランダム化アルゴリズムがあります。私はあなたがすでに答えを受け入れていることを知っていますが、とにかく共有してうれしいです、私は人々がまだこの質問をチェックすることを願っています:)。

Let Used = list of numbers that you sum.
Let Unused = list of numbers that you DON'T sum.
Let tmpsum = 0.
Let S = desired sum you want to reach.

for ( each number x you read )
  toss a coin:
    if it's heads and tmpsum < S
      add x to Used
    else
      add x to Unused

while ( tmpsum != S )
  if tmpsum < S 
    MOVE one random number from Unused to Used
  else
    MOVE one random number from Used to Unused

print the Used list, containing the numbers you need to add to get S

これは、特にランダム入力の場合、動的プログラミングソリューションよりもはるかに高速になります。唯一の問題は、解決策がない場合に確実に検出できないことです(アルゴリズムを数秒間実行することができ、終了しない場合は解決策がないと仮定します)。最小数の要素が選択されています。繰り返しますが、いくつかのロジックを追加して、アルゴリズムを継続させ、特定の停止条件が満たされるまでより少ない要素を持つソリューションを見つけようとすることができますが、これにより遅くなります。ただし、動作するソリューションのみに興味があり、多くの数字があり、目的の合計が非常に大きくなる可能性がある場合、これはおそらくDPアルゴリズムよりも優れています。

このアプローチのもう1つの利点は、DPソリューションには部分的な合計を配列インデックスとして使用することが含まれ、インデックスは自然数であるため、DPソリューションには当てはまることではない、変更なしで負の合理的な数値でも機能することです。もちろん、ハッシュテーブルを使用することもできますが、DPソリューションはさらに遅くなります。

このタスクが何と呼ばれているのか正確にはわかりませんが、それは一種のようです http://en.wikipedia.org/wiki/knapsack_problem.

HEH、私は「不完全な仕様」カードをプレイします(数字が複数回表示できないとは誰も言っていません!)。これを「変更する」問題に減らします。数値を減少させて並べ替え、希望する合計よりも最初のものを見つけてから、合計からそれを減算します(分割と残りはこれをスピードアップできます)。合計= 0またはno no no no sumよりも繰り返されるまで繰り返されます。

完全性を得るには、各合計の加算値の数を追跡し、もちろん最初の数字を追跡し、それをスキップし、追加の数値でプロセスを繰り返すことにより、追加のシーケンスを生成する必要があります。これにより、(7 + 2 + 1)以上の(6 + 4)問題が解決します。

他の人の答えを繰り返す:それはサブセット和の問題です。動的なプログラミング手法によって効率的に解決できます。

以下はまだ言及されていません。問題は擬似-P(または弱い意味ではNP不完全)です。

アルゴリズムの存在(動的プログラミングに基づく)s(sは合計)とn(要素の数)の多項式がこの主張を証明しています。

よろしく。

Okを書いたC++プログラムこのような問題点を解決する.このアルゴリズムはシンプルです:-)

全て手配い配列してい順にしてくれてありがとうございますハードコードされた配列に降順書いてすぐの場所にある申請者の選別アルゴリズム).

次いた架n,posと。最初の店舗の数まで可能な和の組み合わせが見られ、第二の指数の配列からの検索のサービスの要素をそのままにしています。

この機能は最大の番号の配列は以下の番号を入力します。場合等、その押しの数の和のスタックです。ない場合は、その押し出した配列要素のスタック時に、発見の違いを検索び出しを行う再帰.

私は、例- 見44{63,36,22,19,12,9,7,5,3,1}

第36が押された和(最大級の数以下44) 44-36=8押すとn(次の番号で検索) 7押された和 8-7=1のときに押すとn 1押された和

このように44=36+7+1 :-)

#include <iostream>
#include<conio.h>
using namespace std;

int found=0;
void func(int n[],int pos[],int sum[],int arr[],int &topN,int &topP,int &topS)
{
int i=pos[topP],temp;
while(i<=9)
{
    if(arr[i]<=n[topN])
    {
        pos[topP]=i;
        topS++;
        sum[topS]=arr[i];
        temp=n[topN]-arr[i];
        if(temp==0)
            {
                found=1;
                break;
        }
topN++;
        n[topN]=temp;
        temp=pos[topP]+1;
        topP++;
        pos[topP]=temp;
        break;
    }
    i++;
}
if(i==10)
{
    topP=topP-1;
    topN=topN-1;
    pos[topP]+=1;
    topS=topS-1;
    if(topP!=-1)
    func(n,pos,sum,arr,topN,topP,topS);
}
else if(found!=1)
func(n,pos,sum,arr,topN,topP,topS);
}

main()
{
int x,n[100],pos[100],sum[100],arr[10]={63,36,22,19,12,9,7,5,3,1},topN=-1,topP=-1,topS=-1;
cout<<"Enter a number: ";
cin>>x;
topN=topN+1;
n[topN]=x;
topP=topP+1;
pos[topP]=0;
func(n,pos,sum,arr,topN,topP,topS);
if(found==0)
    cout<<"Not found any combination";
else{
cout<<"\n"<<sum[0];
for(int i=1;i<=topS;i++)
    cout<<" + "<<sum[i];
}
getch();
}

コピーすることができ、コードの貼り付けIDE、細:-)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top