01バックパックが所定の位置に転がる

所定の位置にスクロールすることを学んだ後、問題を実行しましょう。
説明は、01バックパックを記述せず
、インプレーススクロールの配列を書き込むための動的計画も記述しません。

シンプル01バックパック:ハッピージンミンポータル

タイトル説明

ジンミンは今日とても幸せです。彼が家で買った新しい家が鍵を受け取るところです。彼の新しい家にはとても広々とした部屋があります。彼をさらに幸せにしているのは、彼の母親が昨日彼に言ったということです。「あなたは部屋でどんなアイテムを買う必要があり、それをどのように飾るか、それがN元を超えない限り、あなたは最終決定権を持っています。」ジンミンは今朝早く予算を立て始めたが、あまりにも多くのものを買いたかったので、それは間違いなく母親が許可したN元を超えるだろう。そのため、彼は各項目の重要度を5つのグレードに分けて規定しました。1から5の整数で表され、5年生が最も重要です。彼はまた、インターネットから各アイテムの価格(すべて整数)をチェックしました。彼は、それがN元(N元に等しくなる可能性がある)を超えないという前提で、各アイテムの価格と重要性の積の合計を最大化することを望んでいます。
j番目のアイテムの価格がv [j]で、重要度がw [j]であると仮定します。合計k個のアイテムが選択され、数がj1、j2、……、jkである場合、合計は次のようになります。 :
v [j1] * w [j1] + v [j2] * w [j2] +…+ v [jk] w [jk]。(その中には掛け算の記号があります)
ジンミンが要件を満たす買い物リストをデザインするのを手伝ってください。

説明を入力してください:

2つの正の整数である最初の行をスペースで区切って入力します。Nm(Nは合計金額を表し、mは購入するアイテムの数です。)
2行目からm + 1行目まで、次の行を入力します。 j行は、j-1の番号が付けられたアイテムの基本データを示し、各行には2つの非負の整数vpがあります(vはアイテムの価格を表し、pはアイテムの重要度を表します)。

出力の説明:

正の整数を出力します。これは、合計金額(<100000000)を超えないアイテムの価格と重要度の積の最大値です。

例1

入る

1000 5
800 2
400 5
300 5
400 3
200 2

出力

3900

備考:

N < 30000,m < 25,v ≤ 10000, 1 ≤ p ≤ 5

思考分析

  1. 動的計画法
  2. 通常のdp2次元配列レコードの場合、現在の行のステータスは前の行にのみ関連し、前のすべての行とは関係ありません。したがって、レコードには2次元配列の代わりに1次元配列を使用できます。これはインプレーススクロールと呼ばれます
  3. 1次元配列を使用する場合、状態カバレッジ回避するために、後ろからにスクロールする必要があることに注意してください(内側のループ後ろから前にループすることによって実装されます)

コード:

#include<iostream>
#include<cmath>//max函数
using namespace std;
const int N = 30;
int val[N]; //价格
int w[N];   //重要度
int dp[30005];
int n;
int main(){
    
    
    int m;
    cin>>n>>m;//输入预算和物品数
    for(int i = 0; i < m; i++)
        cin>>val[i]>>w[i];
    for(int i = 0; i < m; i++)              //一共m个物品
        for(int j = n-1; j >= val[i]; j--)  //从后往前就地滚动 j--
            if(dp[j-val[i]] + val[i] * w[i] > dp[j])//如果选比不选好,那就选
            dp[j] = dp[j-val[i]] + val[i] * w[i];
    cout<<dp[n-1]<<endl;
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_44559752/article/details/106781961