您的位置:首页 > 产品设计 > UI/UE

uestc oj 1218 Pick The Sticks (01背包变形)

2016-09-23 21:30 351 查看
题目链接:http://acm.uestc.edu.cn/#/problem/show/1218

给出n根木棒的长度和价值,最多可以装在一个长 l 的容器中,相邻木棒之间不允许重叠,且两边上的木棒,可以伸一半的长度在容器外,求最大价值量

01背包是取和不取。那这里我们可以把容器长度 l x 2,筷子长度 x 2,就变成了最多两个筷子取一次(伸一半在外面),其余的要么取两次,要么不取。

普通01背包,一维dp[i]表示消耗体积i所得到的最大的价值。

那么这里dp[i][k]表示消耗体积i并有k(k <= 2)个在外面所得到的最大的价值。

//#pragma comment(linker, "/STACK:102400000, 102400000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
typedef pair <int, int> P;
const int N = 4e3 + 5;
LL dp
[5]; //dp[i][k]表示使用i体积有k个木板在露在外面的最大价值
int w
;
LL v
;

int main()
{
int t, n, g;
scanf("%d", &t);
for(int ca = 1; ca <= t; ++ca) {
scanf("%d %d", &n, &g);
LL ans = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d %lld", w + i, v + i);
w[i] <<= 1;
ans = max(ans, v[i]);
}
g <<= 1;
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; ++i) {
for(int j = g; j >= w[i]/2; --j) { //一维背包类似,说明下面只能取一次
for(int k = 0; k <= 2; ++k) {
if(w[i] <= j) //全放在里面
dp[j][k] = max(dp[j - w[i]][k] + v[i], dp[j][k]);
if(k >= 1) //有一半在外面
dp[j][k] = max(dp[j - w[i]/2][k - 1] + v[i], dp[j][k]);
}
}
}
for(int i = 0; i <= 2; ++i) {
ans = max(ans, dp[g][i]);
}
printf("Case #%d: %lld\n", ca, ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: