C++ -- 完全なナップサック問題

1. [テンプレート] バックパック完全_Niuke 質問 Master_Niuke.com

最大容積が V のナップザックを持っています。

n 種類のアイテムがあり、それぞれのアイテムの数は任意で、i 番目のアイテムの体積は vivi 、値は wiwi です。

(1) このバックパックに収納できるアイテムの最大値を見つけますか?

(2) ナップザックがちょうど満杯の場合、最大でいくらの価値を保持できますか?

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

最初の行の 2 つの整数 n と V は、アイテムの数とバックパックの体積を表します。

次の n 行は、それぞれ 2 つの数字 vivi と wiwi を持ち、i 番目の項目の量と値を表します。

1≤n、V≤10001≤n、V≤1000

出力の説明:

出力は2行あり、1行目は1問目の答え、2行目は2問目の答えを出力します。解がない場合は0を出力してください。

例1

入力:

2 6 
5 10 
3 1
出力:
10 
2

例 2

入力:

3 8 
3 10 
9 1 
10 1
出力:
20 
0

例証します:

バックパックを完全に埋めることができません。

例 3

入力:

6 13 
13 189 
17 360 
19 870 
14 184 
6 298 
16 242
出力:
596 
189

例証します:

No.5は2個搭載可能で、最大値は298*2=596となりますが、きっちり詰めたい場合はNo.1を1個のみ搭載可能で、その値は189となります。
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
    int n, V;
    cin >> n >> V;
    int v[n];
    int w[n];
    for (int i = 0; i < n; i++) cin >> v[i] >> w[i];
    int dp[n + 1][V + 1];
    //初始化
    memset(dp, 0, sizeof dp);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= V; j++)
        {
            //动态转移方程
            dp[i][j] = dp[i - 1][j];
            if (j - v[i - 1] >= 0) dp[i][j] = max(dp[i][j], dp[i][j - v[i - 1]] + w[i - 1]);
        }
    }
    cout << dp[n][V] << endl;

    memset(dp, 0, sizeof dp);
    for (int i = 1; i <= V; i++) dp[0][i] = -1;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j <= V; j++)
        {
            dp[i][j] = dp[i - 1][j];
            if (j - v[i - 1] >= 0 && dp[i][j - v[i - 1]] != -1) dp[i][j] = max(dp[i][j], dp[i][j - v[i - 1]] + w[i - 1]);
        }
    }
    cout << (dp[n][V] == -1 ? 0 : dp[n][V]) << endl;
    return 0;
}

2. LeetCode  公式ウェブサイト - 世界中のオタクに愛されるテクノロジー成長プラットフォーム

さまざまな額面のコインを表す整数の配列と合計金額を表すcoins整数が与えられます。amount

合計金額を構成するために必要なコインの最小数を計算して返します。コインの組み合わせが合計金額を構成できない場合は、 を返します -1

各コインの量は無限であると考えることができます。

例 1:

入力:コイン = [1, 2, 5]、金額 =11
出力:3 
説明: 11 = 5 + 5 + 1

例 2:

入力:コイン = [2]、金額 =3
出力: -1

例 3:

入力:コイン = [1]、金額 = 0
出力: 0
class Solution {
public:
    int coinChange(vector<int>& coins, int amount) 
    {
        int n=coins.size();
        vector<int> dp(amount+1);//创建dp表
        for(int i=1;i<=amount;i++) dp[i]=0x3f3f3f3f;//初始化,寻找最小值
        for(int i=1;i<=n;i++)
        {
            for(int j=coins[i-1];j<=amount;j++)
            {
                
                if(j-coins[i-1]>=0)
                {
                    dp[j]=min(dp[j],dp[j-coins[i-1]]+1);//动态转移方程
                }
            }
        }
        return dp[amount]>=0x3f3f3f3f?-1:dp[amount];//返回值
    }
};

3. 交換チェンジ for  LeetCode (リートコード) 公式ウェブサイト – 世界のオタクに愛されるテクノロジー成長プラットフォーム

さまざまな額面のコインを表す整数の配列と、合計金額を表すcoins整数の配列が与えられます。amount

合計金額を構成できるコインの組み合わせの数を計算して返してください。コインの組み合わせが合計金額を構成できない場合は、 を返します0

各金種のコインが無限にあると仮定します。 

タイトル データは、結果が 32 ビットの符号付き整数に収まることを保証します。

例 1:

入力:金額 = 5、コイン = [1, 2, 5]
出力: 4
説明:合計金額を構成するには 4 つの方法があります: 
5=5 
5=2+2+1 
5=2+1+1+1 
5 =1+1+1+1+1

例 2:

入力:金額 = 3、コイン = [2]
出力: 0
説明:合計金額 3 は、金種 2 のコインだけでは構成できません。

例 3:

入力:金額 = 10、コイン = [10] 
出力: 1
class Solution {
public:
    int change(int amount, vector<int>& coins) 
    {
        int n=coins.size();
        vector<int> dp(amount+1);
        dp[0]=1;//初始化
        for(int i=1;i<=n;i++)
        {
            for(int j=coins[i-1];j<=amount;j++)
            {
                
                dp[j]+=dp[j-coins[i-1]];//动态转移方程
            }
        }
        return dp[amount];//返回值
    }
};

4.  世界中のオタクに愛されるテクノロジー成長プラットフォーム LeetCode の公式ウェブサイト

整数を指定するとn合計が になるn完全二乗の最小数を返します。

完全二乗とは、値が別の整数の 2 乗に等しい整数、つまり、値が整数と整数の積に等しい整数です。たとえば、14916すべて完全な正方形ですが、 と3はそうでは11ありません。

例 1:

入力: n =12
出力: 3 
説明:12 = 4 + 4 + 4

例 2:

入力: n =13
出力: 2
13 = 4 + 9
class Solution {
public:
    int numSquares(int n) 
    {
        int m=sqrt(n);
        vector<int> dp(n+1,0x3f3f3f3f);//初始化
       
        dp[0]=0;
        for(int i=1;i<=m;i++)
        {
            for(int j=i*i;j<=n;j++)
            {
                dp[j]=min(dp[j],dp[j-i*i]+1);//动态转移方程
            }
        }
        return dp[n];       
    }
};

おすすめ

転載: blog.csdn.net/weixin_66828150/article/details/132611202