 /**//*
題意:給出一些物品,有價值,數量,價格
還有一些限制,限制的組里面只能選一種物品,問D錢最多能獲得的價值

按組分階段,然后根據物品數量分別做0-1,完全,多重背包(logn)

之前做的都是一維數組的背包,換成滾動數組時注意更新的順序?。。?br>
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cctype>

using namespace std;

const int MAXN = 1030;
const int INF = 1000000000;

int price[MAXN] , num[MAXN] , val[MAXN];
int dp[2][MAXN] , _dp[MAXN];
vector<int> group[MAXN];
bool vi[MAXN];
char str[10000];

int main()
  {
//freopen("in","r",stdin);

int n , D;
while( ~scanf("%d%d",&n,&D) )
 {
group[0].clear();
for(int i = 1 ; i <= n ; i++)
 {
group[i].clear();
vi[i] = false;
scanf("%d%d%d" , &num[i] , &val[i] , &price[i]);
}

int G;
scanf("%d\n",&G);
for(int i = 0 ; i < G ; i++)
 {
gets(str);
for(int j = 0 ;str[j] ; )
 {
if(isdigit(str[j]))
 {
int x = 0;
while(isdigit(str[j]))
x = 10*x + str[j++]-'0';
group[i].push_back(x);
vi[x] = true;
}
else j++;
}
}

for(int i = 1 ; i <= n ; i++)
 {
if(vi[i])continue;
group[G++].push_back(i);
}
int pre = 0 , now = 1;
dp[pre][0] = 0;
for(int i = 1 ; i <= D; i++)
dp[pre][i] = -INF;
for(int i = 0 ; i < G ; i++)
 {
dp[now][0] = 0;
for(int j = 1 ; j <= D; j++)
dp[now][j] = -INF;
for(int ii = 0 ; ii < group[i].size() ; ii++)
 {
int id = group[i][ii];

if(num[id] == 1)//0-1 pack
 {
for(int j = price[id] ; j <= D; j++)
dp[now][j] = max(dp[now][j] , dp[pre][j-price[id]] + val[id]);
}
else if(num[id] == 0)//complete pack
 {
for(int j = 0 ; j <= D; j ++)//多開一個數組
_dp[j] = dp[pre][j];
for(int j = price[id] ; j <= D; j++)
 {
_dp[j] = max(_dp[j] , _dp[j-price[id]] + val[id]);
dp[now][j] = max(dp[now][j] , _dp[j]);
}
}
else//
 {
for(int j = 0 ; j <= D; j ++)//多開一個數組
_dp[j] = dp[pre][j];
int amount = num[id] , k = 1;
while(amount > 0)
 {
if(k>amount)k = amount;
amount -= k;
for(int j = D ; j >= k*price[id] ; j--)//注意是在新的基礎上_dp[j]
 {
_dp[j] = max(_dp[j] , _dp[j-k*price[id]] + k*val[id]);
dp[now][j] = max(dp[now][j] , _dp[j] );
}
k<<=1;
}
}
}
for(int j = 0 ; j <= D; j++)//記得要更新??!
dp[now][j] = max(dp[now][j] , dp[pre][j]);
swap(pre,now);
}
if(dp[pre][D] < 0)puts("i'm sorry ");
else printf("%d\n",dp[pre][D]);
}
return 0;
}
|
|
常用鏈接
隨筆分類
Links
搜索
最新評論

|
|