質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

1668閲覧

ナップサック問題を一次元の配列を使って解きたい

MakiAram

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2022/01/05 18:26

編集2022/01/05 19:33

前提・実現したいこと

ナップサック問題を解いています、二次元配列を用いて実現する方法はわかりました。
次に一次元配列を二つ使用する方法や、一つだけ使用して実現する方法を考えているのですが、いまいちどのようにコードを書けばよいかがわかりません。
どうかよろしくお願いします。

発生している問題

ナップサック問題を二次元配列を用いずに実現したい。
ソースコードにある二次元配列dpを一次元配列で実現させたい。
ここら辺をどうすればいいか悩んでいます

for(i=0;i<=N;i++){ for(j=0;j<=M;j++){ int x,y=-1; if(i!=0){ x = dp[i-1][j]; if(j>=w[i])y = dp[i-1][j-w[i]]+v[i]; if(x>y)dp[i][j]=x; else dp[i][j]=y;

該当のソースコード

c

1#include <stdio.h> 2#define M 10 3#define N 5 4 5int w[N+1]={0,2,3,4,5,6}; 6int v[N+1]={0,4,5,8,9,11}; 7int dp[M+1][M+1]; 8 9int main(void){ 10 int i,j,k; 11 for(i=0;i<=M;i++)for(j=0;j<=M;j++)dp[i][j]=0; 12 13 for(i=0;i<=N;i++){ 14 for(j=0;j<=M;j++){ 15 int x,y=-1; 16 if(i!=0){ 17 x = dp[i-1][j]; 18 if(j>=w[i])y = dp[i-1][j-w[i]]+v[i]; 19 if(x>y)dp[i][j]=x; 20 else dp[i][j]=y; 21 } 22 printf("%2d ",dp[i][j]); 23 } 24 printf("\n"); 25 } 26 printf("\nanswer = %d\n",dp[N][M]); 27 return 0; 28}

補足情報(FW/ツールのバージョンなど)

c言語

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/01/05 18:38

>いまいちわかりません 何が分からないのか分かりません。
actorbug

2022/01/06 11:34

まずは、「ナップサック問題 一次元 配列」あたりで検索しましょう。 以下のページにも、まずは自分で検索するように書かれています。 質問するときのヒント 1-2. 投稿前に検索し、できるところまで自分でやってみましょう https://teratail.com/help/question-tips#questionTips1-2
guest

回答3

0

ベストアンサー

二次元配列を一次元配列に機械的に置き換えると、

c

1#include <stdio.h> 2#define M 10 3#define N 5 4#define K(i,j) ((i)*(M+1)+(j)) // 2変数を一次元配列の添字に変換 5 6int w[N+1]={0,2,3,4,5,6}; 7int v[N+1]={0,4,5,8,9,11}; 8int dp[(M+1)*(M+1)]; // dp は一次元配列 9 10int main(void){ 11 int i,j,k; 12 for(i=0;i<=M;i++)for(j=0;j<=M;j++)dp[K(i,j)]=0; 13 14 for(i=0;i<=N;i++){ 15 for(j=0;j<=M;j++){ 16 int x,y=-1; 17 if(i!=0){ 18 x = dp[K(i-1,j)]; 19 if(j>=w[i])y = dp[K(i-1,j-w[i])]+v[i]; 20 if(x>y)dp[K(i,j)]=x; 21 else dp[K(i,j)]=y; 22 } 23 printf("%2d ",dp[K(i,j)]); 24 } 25 printf("\n"); 26 } 27 printf("\nanswer = %d\n",dp[K(N,M)]); 28 return 0; 29}

結果だけを得られれば良いのであれば、こんな風にも書けます。

C

1#include <stdio.h> 2 3#define M 10 4#define N 6 5 6int w[N] = { 0, 2, 3, 4, 5, 6 }; 7int v[N] = { 0, 4, 5, 8, 9, 11 }; 8int dp[N], m; // dp は一次元配列 9 10void f(int i, int w0, int v0) 11{ 12 if (w0 > M) return; 13 if (v0 > m) m = v0; 14 if (i < N) { 15 dp[i] = 1; f(i+1, w0 + w[i], v0 + v[i]); 16 dp[i] = 0; f(i+1, w0, v0); 17 } 18} 19 20int main(void) 21{ 22 f(0, 0, 0); 23 printf("answer = %d\n", m); 24}

追記
結果を得るだけなら dp は不要でした
dp[N],dp[i] = 1;dp[i] = 0; は削除できます。

投稿2022/01/06 09:55

編集2022/01/07 05:54
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

MakiAram

2022/01/06 16:28

なるほど、このような表現方法があったのですね!とても参考になりました、ありがとうございました!
jimbe

2022/01/07 08:24

> 結果を得るだけなら dp は不要 2 → 1 次元を超えて 0
kazuma-s

2022/01/07 17:07

「一次元の配列を使って解きたい」という質問に対して 一次元配列を使わない回答を追記して申し訳ありませんでした。
guest

0

ソースコードにある二次元配列dpを一次元配列で実現させたい。

ここら辺をどうすればいいか悩んでいます

単に,【その二次元配列と要素数が同一な一次元配列】を用いれば良いのではないでしょうか.

「扱うべき個数の情報を扱える」っていうのが「配列」の役目でしょうから.
(あとは要素アクセス位置をそれに合わせるだけ)

投稿2022/01/06 02:01

fana

総合スコア11658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2022/01/06 02:04

「そんな自明な話をしてるわけじゃない」という場合には, その旨と「じゃあ何の話なのか?」という事柄とを明確にしていただきたく.
guest

0

dp[M+1]を使いまわしたいという意味でしたら、下記の記事が参考になると思います。(actorbugさんのおっしゃる通り、本当は自分で調べてもらいたいのですが…)
https://qiita.com/drken/items/68b8503ad4ffb469624c

ポイントは、jの大きい方から順に更新していくところです。

投稿2022/01/06 14:57

luuguas

総合スコア492

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問