您的位置:首页 > 其它

HUST 1354 Rubiks

2016-02-16 19:07 204 查看
背包。注释写详细了。

本想这样写:每个组内各自做背包,然后组间做背包,但是由于这题M=10000,时间复杂度太大。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<functional>
using namespace std;

const int maxn = 10000 + 10;
int n, m, g;

vector<int>G[20];

int cost[1000 + 10];
int val[1000 + 10];
int y[20];
bool flag[1000 + 10];
int dp1[10000 + 10];
int dp2[10000 + 10];

void init()
{
memset(flag, 0, sizeof flag);
for (int i = 1; i <= g; i++) G[i].clear();
}

int main()
{
while (~scanf("%d%d", &n, &m)){

for (int i = 1; i <= n; i++) scanf("%d", &cost[i]);
for (int i = 1; i <= n; i++) scanf("%d", &val[i]);
scanf("%d", &g);
init();
for (int i = 1; i <= g; i++)
{
int f;
scanf("%d", &f);
for (int j = 1; j <= f; j++)
{
int id;
scanf("%d", &id);
G[i].push_back(id);
flag[id] = 1;
}
scanf("%d", &y[i]);
}

memset(dp1, 0, sizeof dp1);

//没有组的归为一组
for (int i = 1; i <= n; i++)
{
if (flag[i]) continue;
for (int j = m; j >= cost[i]; j--)
dp1[j] = max(dp1[j], dp1[j - cost[i]] + val[i]);
}

for (int k = 1; k <= g; k++)
{
//此时dp2数组存储了之前的所有组合最优解
for (int i = 1; i <= m; i++) dp2[i] = dp1[i];

//接下来假设不买完这个组合内的魔方,这样DP的话事实上也存在买完的组合,但会被之后的dp2更新,所以不存在问题
for (int s = 0; s < G[k].size(); s++)
{
for (int j = m; j >= cost[G[k][s]]; j--)
{
dp1[j] = max(dp1[j], dp1[j - cost[G[k][s]]] + val[G[k][s]]);
}
}

//假设买完,用dp2更新
int sum_cost = 0, sum_val = y[k];
for (int s = 0; s < G[k].size(); s++)
{
sum_cost = sum_cost + cost[G[k][s]];
sum_val = sum_val + val[G[k][s]];
}

for (int j = m; j >= sum_cost; j--)
{
dp2[j] = max(dp2[j], dp2[j - sum_cost] + sum_val);
}

//然后dp1和dp2存下最大值
for (int i = 0; i <= m; i++) dp1[i] = max(dp1[i], dp2[i]);
}

printf("%d\n", dp1[m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: