JakeLin- [ACMトレーニング]漢方薬-DP / 01バックパック-ソリューション

トピックの説明
チェンチェンは才能のある子供で、彼の夢は世界で最も優れた医師になることです。このため、彼は近くで最も権威のある医師を教師として崇拝したかったのです。彼の資格を判断するために、医者は彼に問題を与えました。医者は彼をハーブでいっぱいの洞窟に連れて行き、彼に言いました:「子供、この洞窟にはいくつかの異なるハーブがあります。それぞれの植物を選ぶにはしばらく時間がかかり、それぞれの植物には独自の価値があります。私はそれをあげますあなたには一定の期間があり、この期間中にいくつかのハーブを集めることができます。あなたが賢い子供なら、集めたハーブの合計値を最大化できるはずです。 " 
あなたがチェンチェンであれば、このタスクを完了することができますそうですか?

入力

入力の最初の行に2つの整数T(1 <= T <= 1000)とM(1 <= M <= 100)をスペースで区切って入力します。Tは薬の収集に利用できる合計時間、Mは洞窟を表しますフィールド内のハーブの数。次のM行の各行には、1〜100(1〜100を含む)の2つの整数が含まれ、それぞれ特定のハーブを選択した時間とこのハーブの値を表します。

アウトプット

1行を出力します。この行には整数のみが含まれ、指定した時間内に収穫できるハーブの最大合計値を表します。

入力例

70 3 
71 100 
69 1 
1 2

出力例

元のタイトルのリンク:漢方薬

1. 0/1バックパックダイナミックプログラミングの考え方は次のとおりです。

このI-樹木医学の前に、私が持っている2つの選択肢が
1。私はそれを取るでしょう。私はそれを拾う場合、私は時間が減少します持っているので、値Iが増加を受けている間、
2を、私はそれを採用していません:選択しない場合、時間は減少せず、値は増加せず、ステップi-1の値が残ります。


第2に、従来の方法でDPアレイを設計しました。int dp[maxn][maxn2];その原理は非常に重要
dp[i][j]です。表現される値は何ですか。この状態での最大値です!何州?i番目の項目(最初のi-1は既に配置されています)を考慮しており、最大値である時間jがかかる状態です。
つまり、このように考えることができます。プログラム全体が実際にdp配列を構築しています。これは、3つの要素[項目数]-[残りの量]-[合計値]を1つの状態に要約でき、エンドポイントはdp[所有物品][所有时间]


1つに戻って、2つの状況の分析を続けます。

1. i番目の項目を分析します

次に、dp [i] [*]を決定する必要があります。このとき、コスト[i]、値[i]はi番目のアイテムのコストと時間を表します。

2. 残り時間jを再分析します。

  • 残り時間がコスト[i]未満の場合、確実に手に取ることはできません。
  • 十分な時間があれば、次のことを考慮する必要があります。
    • 選択すると、それは新しい状態を構成し、残りの時間はコスト[i]を削減し、値は値[i]だけ増加します。dp [i] [j]-> dp [i-1] [ jコスト[i]] +値[i]
    • 選択しない場合、時間を費やすことも値を増やすこともしません。状態dp [i] [j]はdp [i-1] [j]と同じです
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 100 + 10;
const int maxn2 = 1000 + 10; 
int cost[maxn];
int value[maxn];
int dp[maxn][maxn2];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>cost[i]>>value[i];
    }
    for(int i=1;i<=m;i++){  //第i个物品(药)是否放入背包(采它) 
        for(int j=1;j<=n;j++){  // 遍历可能的时间情况 
            if(j>=cost[i]){  //max(采,不采) 
                dp[i][j] = max(dp[i-1][j-cost[i]]+value[i],dp[i-1][j]);
            }else{  //cost[i]:采第i个药要花的时间,如果j不够肯定采不了 
                dp[i][j] = dp[i-1][j];    
            }
        }
    }
    cout<<dp[m][n];
    return 0;
}

 その後の最適化では、dp配列が1次元削除され、i(i医薬品)を表す次元が小さくなり、dp配列[下から上へ]構築されます

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 110;
const int tmaxn = 1010;
int cost[maxn],value[maxn];
int dp[tmaxn];
int main(){
    int t,m;
    cin>>t>>m;
    for(int i=1;i<=m;i++){
        cin>>cost[i]>>value[i];
    }
    for(int i=1;i<=m;i++){
        for(int j=t;j>=cost[i];j--){
            dp[j] = max(dp[j],dp[j-cost[i]]+value[i]);
        }
    }
    cout<<dp[t];
    return 0;
}

 

上記は、0/1バックパックの問題を解決するための2つのDPアルゴリズムの使用です。 

元の記事を20件公開 15 獲得 ビュー216

おすすめ

転載: blog.csdn.net/qq_37414463/article/details/105386756