hdu 2844&poj 1742 Coin---多重リュックサック--2つの方法
3329 ワード
标题:あなたはN種類のコインを持っていて、それぞれの価値A[i]、それぞれの数C[i]を聞いています.Mを超えない場合、私たちはこれらのコインを使って、支払いはどのような状況がありますか.つまり:1,2,3,4,5,...,Mこのように多くの場合、あなたのコインでお金を探さずに、いくら支払うことができますか.
例:
コインを持っています.価値は2、個数は2です.では、3元は払えません.2元か4元しか払えません.の
OK、問題の意味が悪いのはそうです.
では、ここには2つの方法があります!
分析:
では、ここでは多重リュックで解決することができ、価値と重量を同じw[i]=A[i]と見なすことができます.Mをリュックサックにします.では、dpの後、dp[i]が表す意味は、i元を超えない場合、持っているコインで構成できる最大金額であることがわかります.明らかに、dp[i]=iは、持っているお金で、ちょうどi元を構成することができるという意味で、馬に乗ることができます.
flag[i]でお金をiにできるかどうかを表す場合
time[j]は、j元を構成する場合、i番目のコインの個数で
例:
コインを持っています.価値は2、個数は2です.では、3元は払えません.2元か4元しか払えません.の
OK、問題の意味が悪いのはそうです.
では、ここには2つの方法があります!
分析:
では、ここでは多重リュックで解決することができ、価値と重量を同じw[i]=A[i]と見なすことができます.Mをリュックサックにします.では、dpの後、dp[i]が表す意味は、i元を超えない場合、持っているコインで構成できる最大金額であることがわかります.明らかに、dp[i]=iは、持っているお金で、ちょうどi元を構成することができるという意味で、馬に乗ることができます.
//281MS 648K
#include <stdio.h>
#include <string.h>
#define MAX 102
int ans;//
int n,m;
int A[MAX],C[MAX];
int dp[100005];
void ZeroOne(int V,int W)
{
for(int i = m; i >= V; i--)
//dp[i] = dp[i]>dp[i-V]+W ? dp[i]:dp[i-V]+W;
if(dp[i]<dp[i-V]+W)
{
dp[i] = dp[i-V]+W;//
if(dp[i] == i) ans ++;// dp , dp[j] j , dp[i]=dp[i-V]+W;
}
}
int main()
{
while(scanf("%d%d",&n,&m),n+m)
{
ans = 0;
memset(dp,0,sizeof(dp));
for(int i = 1; i <= n; i ++) scanf("%d",&A[i]);
for(int i = 1; i <= n; i ++) scanf("%d",&C[i]);
for(int i = 1; i <= n; i ++)
{
if(A[i]*C[i] >= m)
{
for(int j = A[i]; j <= m; j ++)
//dp[j] = dp[j]>dp[j-A[i]]+A[i] ? dp[j]:dp[j-A[i]]+A[i]; //
if(dp[j]<dp[j-A[i]]+A[i]) // ans
{
dp[j] = dp[j-A[i]]+A[i];
if(dp[j] == j) ans ++; // dp , dp[j] j , dp[i]=dp[i-V]+W;
}
}
else
{
int k = 1;
while(k <= C[i])
{
ZeroOne(A[i]*k,A[i]*k);
C[i] -= k;
k *= 2;
}
ZeroOne(C[i]*A[i],C[i]*A[i]);
}
}
//for(int i = 1; i <= m; i ++) if(dp[i]==i)ans++;// hdu, poj ans, , 2654ms........ 。。。。。
printf("%d
",ans);
}
return 0;
}
ではもう一つの方法がありますflag[i]でお金をiにできるかどうかを表す場合
time[j]は、j元を構成する場合、i番目のコインの個数で
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 100005
int N,M;
int A[MAX],C[MAX];
bool flag[MAX];
int time[MAX];
int main()
{
while(cin >> N >> M)
{
if(!N && !M)break;
for(int i = 0; i < N; i ++) cin >> A[i];
for(int i = 0; i < N; i ++) cin >> C[i];
int ans = 0;
memset(flag,false,sizeof(flag));
flag[0] = true;
for(int i = 0; i < N; i ++){
memset(time,0,sizeof(time));
for(int j = A[i]; j <= M; j ++){// , j , j-A[i] --( , ), j , i C[i]
if(!flag[j] && flag[j-A[i]] && time[j-A[i]]+1 <= C[i]){
flag[j] = true;
time[j] = time[j-A[i]]+1;
ans ++;
}
}
}
cout << ans <<endl;
}
return 0;
}
個人の愚かな観点、指摘と討論を歓迎します