ハッピージンミンバックパック

C.ハッピージンミン(ハッピー)【ディスカッション】
説明
ジンミンは今日とても幸せです。家で買った新しい家が鍵をもらおうとしています。新しい家には彼専用の広々とした部屋があります。彼をさらに幸せにしているのは、彼の母親が昨日彼に言ったということです。「あなたは部屋でどんなアイテムを買う必要があり、それをどのように飾るか、それが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]。(*は乗算記号です)
Jinmingが要件を満たす買い物リストを設計するのを手伝ってください。


最初のファイルhappy.inの入力入力行、スペースで区切られた2つの正の整数:
Nm
(ここで、N(<30000)は合計金額を表し、m(<25)から目的の購入アイテム数
まで)。2行目からm + 1行目、j行目はj-1の番号が付けられた項目の基本データを示し、各行には2つの非負の整数があります。
vp
(vはアイテムの価格(v≤10000)を示し、pはアイテムの重要性(1〜5)を示します)

出力
出力ファイルhappy.outには、正の整数が1つだけあります。これは、合計金額(<100000000)を超えないアイテムの価格と重要度の積の最大値です。

サンプル
入力コピー
1000年5
800 2
400 5
300 5
400 3
200 2
出力
3900

アイデア
マネー-------》ウェイト

重要性----》価値

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue <int,vector<int>,less<int> > q;
priority_queue <int,vector<int>,greater<int> > pp;
vector <int> aa;
typedef struct sty{
    
    
                   int str;
                    int end;
                }ss;
int cmp(ss a,ss b)
{
    
    
       if(a.str==b.str)
        return a.end<b.end;

        return a.str<b.str;
    }
int pan(int n)
{
    
    
       for(int i=2;i<=sqrt(n);i++)
            if(n%i==0)
            return 0;

        return 1;

    }
int pan1(int n)
{
    
    
       if(n%10+n/10%10==n/100%10+n/1000)
        return 1;
    return 0;
    }
int max1(int x,int y)
{
    
    
            if(x>y)
            return x;
        return y;
    }
int min1(int x,int y)
{
    
    
            if(x>y)
                return y;
            return x;
        }
const int maxn=1e6+888;
const int N=1006;
ll n,m,sum=0,minx=-1;
int a[maxn];

int pre[maxn],sz[maxn],rk[maxn];
int c[maxn];

void f(ll *p)
{
    
    
    *p/=2;
}
void ff(ll *p)
{
    
    
    *p=3*(*p)+1;
}

int main(){
    
    

 int x;
 int z,t;
 cin>>z>>t;
 for(int i=0;i<t;i++)
 {
    
    
     cin>>a[i];
     cin>>x;
     c[i]=a[i]*x;
 }
 for(int i=0;i<t;i++)
 {
    
    
     for(int j=z;j>=a[i];j--)
     {
    
    
         pre[j]=max(pre[j],pre[j-a[i]]+c[i]);
     }
 }
 cout<<pre[z];
   return 0;
}

1:01バックパック問題
(各オブジェクトは1回しか取得できません。値を最大化するには、特定のスペースにオブジェクトを取得する必要があります)

書き方は2つあり、1つは2次元配列、もう1つは1次元配列(省スペース)です。

1. 2次元dpテンプレート:(複数のサンプル入力がある場合、このメソッドがdp配列を空にする必要がないのは奇妙です)

状態遷移方程式:dp [i] [j] = max(dp [i-1] [j]、dp [i-1] [j-wei [i]] + val [i]);

基本操作:

if(j>=wei[i])
{
    
    
	dp[i][j]=max(dp[i-1][j],dp[i-1][j-wei[i]]+val[i]);//i为面对第几个物体了
    //j为所占的空间大小下,dp数组存的是对应的价值
}
else//这种写二维的方式可不清空 
{
    
    
	dp[i][j]=dp[i-1][j];
}

2. 1次元のdpテンプレート(この方法でdp配列をクリアすることを忘れないでください。また、これは前の状態であるため、後ろから前への逆の順序にも注意してください。そうしないと、計算が繰り返されます)

テンプレート:

状態遷移方程式:dp [j] = max(dp [j]、dp [j-wei [i]] + val [i]);

基本操作:

memset(dp,0,sizeof(dp));//一维记得清空 
for(int i=1;i<=n;++i)
{
    
    
	for(int j=v;j>=wei[i];--j)
	{
    
    
		dp[j]=max(dp[j],dp[j-wei[i]]+val[i]);
	}
}
cout<<dp[v]<<endl;

概要:簡単に言えば、オブジェクトごとに2つの選択肢があります。取得するかしないかです。取得しない場合は、前の状態を継承します。それ以外の場合は、前の状態のdp値に現在のオブジェクト。

2:完全なナップサック問題
(各オブジェクトは数え切れないほど取得できます。値を最大化するには、特定のスペースにオブジェクトを取得する必要があります)

ボード:

状態遷移方程式:dp [j] = max(dp [j]、dp [jw [i]] + v [i]);

基本操作:

for(i=1;i<=n;i++)
      for(j=w[i];j<=m;j++)  //注意此处与01背包不同,01为倒序
 
             dp[j]=max(dp[j],dp[j-w[i]]+v[i]);

最適化:2つのアイテムiとjがc [i] <= c [j]とw [i]> = w [j]を満たす場合、アイテムjは考慮せずに削除されます。

おすすめ

転載: blog.csdn.net/qq_52172364/article/details/112756610