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は考慮せずに削除されます。