dp - 3维背包(东四省)
题意:
给你 n 张卡片,总共可以消耗的法力值,求最多可以造成多少伤害, 卡片分为2种,一种是魔法卡,使用后可以使所有的连环卡的费用全部减1,另一种是连环卡,因魔法卡的使用可以使其费用减1,问最终最多可以造成多少的伤害
思路分析 :
比赛的时候大脑短路了,基本不愿意去想东西了,导致题目没有出来,这个题就是一个 01背包,但是增加了一个限制条件,所以我们多增加一维表示到当前位置,所使用的魔法卡的数量,但是呢,还有一个很关键的地方,就是我们要先对卡片经行一个排序的预处理,这样在搞 dp的时候,才不会对后续有任何的影响,排序的时候,优先使用魔法卡,然后两者都是的卡,剩下的卡就随意了。
代码示例:(未测试)
#define ll long long
const int maxn = 1e6+5;
const int mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f; int n, w; struct node
{
int w, x, p1, p2; }pre[505];
int dp[505][505][505];
int cnt = 0; bool cmp1(node a, node b){
if (a.p1 == b.p1) return a.p2 < b.p2;
return a.p1 > b.p1;
} bool cmp2(node a, node b){
if (a.w == b.w) return a.x > b.x;
return a.w < b.w;
} void fun(){ for(int i = 1; i <= n; i++){
for(int j = 1; j <= w; j++){
for(int k = 0; k <= min(i, cnt); k++){ // 使用魔法卡
if (pre[i].p1 && !pre[i].p2) { // 1 0
if (j >= pre[i].w && k)
dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-pre[i].w][k-1]+pre[i].x);
else dp[i][j][k] = dp[i-1][j][k];
}
else if (pre[i].p1 && pre[i].p2){ // 1 1
int cost = max(pre[i].w-k+1, 0);
//if (i == 2 && j == 2) printf("cost = %d\n", cost);
if (j >= cost && k){
dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-cost][k-1]+pre[i].x);
}
else dp[i][j][k] = dp[i-1][j][k];
}
else if (!pre[i].p1 && pre[i].p2){ // 0 1
int cost = max(pre[i].w-k, 0);
if (j >= cost && k){
dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-cost][k]+pre[i].x);
}
else dp[i][j][k] = dp[i-1][j][k];
}
else { // 0 0
if (j >= pre[i].w){
dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-pre[i].w][k]+pre[i].x);
}
else dp[i][j][k] = dp[i-1][j][k];
}
//printf("+++%d %d %d = %d \n",i, j, k, dp[i][j][k]);
}
}
}
} void init(){
int pos1 = -1, pos2 = -1; for(int i = 1; i <= n; i++){
if (pre[i].p1 && !pre[i].p2) {
pos1 = i;
break;
}
}
for(int i = n; i >= 1; i--){
if (pre[i].p1 && !pre[i].p2) {
pos2 = i;
break;
}
}
if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2); pos1 = pos2 = -1;
for(int i = 1; i <= n; i++){
if (pre[i].p1 && pre[i].p2) {
pos1 = i;
break;
}
}
for(int i = n; i >= 1; i--){
if (pre[i].p1 && pre[i].p2) {
pos2 = i;
break;
}
}
if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2); pos1 = pos2 = -1;
for(int i = 1; i <= n; i++){
if (!pre[i].p1 && !pre[i].p2) {
pos1 = i;
break;
}
}
for(int i = n; i >= 1; i--){
if (!pre[i].p1 && !pre[i].p2) {
pos2 = i;
break;
}
}
if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2); pos1 = pos2 = -1;
for(int i = 1; i <= n; i++){
if (!pre[i].p1 && pre[i].p2) {
pos1 = i;
break;
}
}
for(int i = n; i >= 1; i--){
if (!pre[i].p1 && pre[i].p2) {
pos2 = i;
break;
}
}
if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2);
} int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout); cin >> n >> w;
for(int i = 1; i <= n; i++){
scanf("%d%d%d%d", &pre[i].w, &pre[i].x, &pre[i].p1, &pre[i].p2);
if (pre[i].p1 == 1) cnt++;
}
sort(pre+1, pre+1+n, cmp1);
init();
for(int i = 1; i <= n; i++){
printf("%d%d%d%d\n", pre[i].w, pre[i].x, pre[i].p1, pre[i].p2);
}
memset(dp, 0x8f, sizeof(dp));
for(int j = 0; j <= w; j++) {
dp[0][j][0] = 0;
}
fun();
int ans = 0;
for(int i = 0; i <= cnt; i++) ans = max(ans, dp[n][w][i]);
printf("%d\n", ans);
return 0;
}
/*
4 3
1 3 0 1
1 0 0 0
3 3 1 1
3 4 1 0 3 3
3 3 1 1
2 3 1 1
1 3 1 1 3 4
3 10 1 1
30 400 1 1
4 200 1 1 5 5
6 50 1 1
3 30 0 1
3 3 1 0
3 200 0 0
3 6 1 0 6 4
1 3 1 0
2 5 0 0
1 2 0 1
2 2 1 1
3 4 0 1
1 1 1 0
*/
dp - 3维背包(东四省)的更多相关文章
- 二维背包(钟神想要的)(不是DP)
[问题描述] 背包是个好东西,希望我也有.给你一个二维的背包,它的体积是? × ?.现在你有一些大小为1× 2和1×3的物品,每个物品有自己的价值.你希望往背包里面装一些物品,使得它们的价值和最大,问 ...
- HDU 2159 FATE (DP 二维费用背包)
题目链接 题意 : 中文题不详述. 思路 : 二维背包,dp[i][h]表示当前忍耐值为i的情况下,杀了h个怪得到的最大经验值,状态转移方程: dp[i][h] = max(dp[i][h],dp[i ...
- dp 二维乃至多维背包
洛谷P1855 榨取kkksc03 分析:套路是很明显的01背包,但是这时受约束的变量有两个了,这种情况下就该用多维背包了 分析方法一样的,用dp[i][j][k]表示从前i个愿望中挑选总时间和总金钱 ...
- dp之二维背包poj2576
题意:有一群sb要拔河,把这群sb分为两拨,两拨sb数只差不能大于1,输出这两拨人的体重,小的在前面...... 思路:把总人数除2,总重量除2,之后你会发现就是个简单的二维背包,有两个限制..... ...
- (第三场) A PACM Team 【dp,五维背包】
链接:https://www.nowcoder.com/acm/contest/141/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- hdu 4501 小明系列故事——买年货_二维背包
题目:你可以有v1元,v2代金券,v3个物品免单,现在有n个商品,商品能用纸币或者代金券购买,当然你可以买v3个商品免费.问怎么最大能买多少价值 题意: 思路二维背包,dp[v1][v2][v3]=M ...
- poj1742 多维背包
普通的多维背包做不了,需要优化一下 但是没有学优化..别的方法也是可以做的 省去一个 表示阶段的 i 维度,dp[j]表示面值为j的钱是否被凑出来了,used[j]表示第i种硬币在凑面值为j的时候被用 ...
- HDU 2159 FATE (二维背包)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 解题报告:这题实际上是一个二维的背包问题,也可以由01背包扩展而来,01背包用一维数组,可想而知 ...
- rqnoj-329-刘翔!加油!-二维背包
注意排除干扰项. 因为价值不会相等,所以价值的多少与本题没有任何关系,. 所以价值为干扰项,所以不用考虑. 二维背包,简单求解. #include<stdio.h> #include< ...
随机推荐
- 【codeforces 766B】Mahmoud and a Triangle
time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...
- SVN:符号
问号:未纳入SVN控制之下的新文件感叹号:已经修改过还没上传的文件红叉:准备删除尚未提交绿勾:从服务器上取下来没修改过的文件黄色感叹号:发生冲突蓝色加号:准备加到服务器上还没提交
- 机器学习——集成学习之Stacking
摘自: https://zhuanlan.zhihu.com/p/27689464 Stacking方法是指训练一个模型用于组合其他各个模型.首先我们先训练多个不同的模型,然后把之前训练的各个模型的输 ...
- 对象转json字符串案例
测试对象与json字符串的转换 json字符串转对象 Stringstr = "{\"id\":\"1001\",\"name\" ...
- Linux 内核存取 I/O 和内存空间
一个 PCI 设备实现直至 6 个 I/O 地址区. 每个区由要么内存要么 I/O 区组成. 大部分 设备实现它们的 I/O 寄存器在内存区中, 因为通常它是一个完善的方法(如同在" I/O ...
- Java Developer's Guide to SSL Certificates
https://www.codebyamir.com/blog/java-developers-guide-to-ssl-certificates Overview When developing w ...
- 16python的map函数,filter函数,reduce函数
map num_l = [1,6,8,9] def map_test(func,array): ret = [] for i in array: res = func(i) ret.append(re ...
- Django 中配置MySQL数据库
在Django的项目中会默认使用sqlite的数据库 配置MySQL需要在setting.py 里加入以下设置: 配置数据库 DATABASES = { 'default': { 'ENGINE': ...
- 利用Feed43为网站自制RSS源
什么是RSS,它可以做什么 快2020年了,RSS日渐式微,我也是去年机缘巧合下才开始使用的,以前只是听说过.RSS,全称Really Simple Syndication,又称简易信息聚合(也叫聚合 ...
- org.apache.subversion.javahl.ClientException: Item is not readable 解决办法
在使用eclise安装的插件subclipse查看svn的提交历史记录的时候,提示org.apache.subversion.javahl.ClientException: Item is not r ...