题意:

给你 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维背包(东四省)的更多相关文章

  1. 二维背包(钟神想要的)(不是DP)

    [问题描述] 背包是个好东西,希望我也有.给你一个二维的背包,它的体积是? × ?.现在你有一些大小为1× 2和1×3的物品,每个物品有自己的价值.你希望往背包里面装一些物品,使得它们的价值和最大,问 ...

  2. HDU 2159 FATE (DP 二维费用背包)

    题目链接 题意 : 中文题不详述. 思路 : 二维背包,dp[i][h]表示当前忍耐值为i的情况下,杀了h个怪得到的最大经验值,状态转移方程: dp[i][h] = max(dp[i][h],dp[i ...

  3. dp 二维乃至多维背包

    洛谷P1855 榨取kkksc03 分析:套路是很明显的01背包,但是这时受约束的变量有两个了,这种情况下就该用多维背包了 分析方法一样的,用dp[i][j][k]表示从前i个愿望中挑选总时间和总金钱 ...

  4. dp之二维背包poj2576

    题意:有一群sb要拔河,把这群sb分为两拨,两拨sb数只差不能大于1,输出这两拨人的体重,小的在前面...... 思路:把总人数除2,总重量除2,之后你会发现就是个简单的二维背包,有两个限制..... ...

  5. (第三场) A PACM Team 【dp,五维背包】

    链接:https://www.nowcoder.com/acm/contest/141/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...

  6. hdu 4501 小明系列故事——买年货_二维背包

    题目:你可以有v1元,v2代金券,v3个物品免单,现在有n个商品,商品能用纸币或者代金券购买,当然你可以买v3个商品免费.问怎么最大能买多少价值 题意: 思路二维背包,dp[v1][v2][v3]=M ...

  7. poj1742 多维背包

    普通的多维背包做不了,需要优化一下 但是没有学优化..别的方法也是可以做的 省去一个 表示阶段的 i 维度,dp[j]表示面值为j的钱是否被凑出来了,used[j]表示第i种硬币在凑面值为j的时候被用 ...

  8. HDU 2159 FATE (二维背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 解题报告:这题实际上是一个二维的背包问题,也可以由01背包扩展而来,01背包用一维数组,可想而知 ...

  9. rqnoj-329-刘翔!加油!-二维背包

    注意排除干扰项. 因为价值不会相等,所以价值的多少与本题没有任何关系,. 所以价值为干扰项,所以不用考虑. 二维背包,简单求解. #include<stdio.h> #include< ...

随机推荐

  1. 一次接口压力测试qps极低原因分析及解决过程

    一次接口压力测试qps极低原因分析及解决过程 9-2日在做内部的性能测试相关培训时,发现注册接口压力测试qps极低(20左右),这个性能指标远不能达到上线标准 ,经过一系列调试,最后定位 98%的时间 ...

  2. CodeChef Ada Pawns

    最小割 留下最多的点 形如左上或者右上没有点的点一定会留下 对于斜着的关系的两个点不能共存 黑白行染色! 白行的点称为 白点,黑点类似 反着连关系 对于一定会留下的,S到白点,黑点到T,都连inf 不 ...

  3. es6笔记 day3---Promise

    作用:解决异步回调问题 先知道它的大概语法就好了,这个东西需要平时用到才知道它的用处 语法: let promise= new Promise(function(resolve,reject){ // ...

  4. 移动端开发touchstart,touchmove,touchend事件详解和项目

    移动端开发touchstart,touchmove,touchend事件详解和项目 最近在做移动端的开发,在一个“服务商管理”页面使用到了触摸事件"touchstart",&quo ...

  5. String、StringBuffer和StringBuild区别

    String String是不可变对象,即对象一旦生成,就不能被更改.对String对象的改变会引发新的String对象的生成. String s = "abcd"; s = s+ ...

  6. hdu 6852Path6(最短路+最小割)

    传送门 •题意 有n个城市,标号1-n 现花费最小的代价堵路 使得从1号城市到n号城市的路径边长 (注意只是变长不是最长) 堵一条路的代价是这条路的权值 •思路 在堵路以前,从1到n的最小路径当然是最 ...

  7. VisualStudio 断点调试详解

    本文详细告诉大家 VisualStudio 断点调试的功能和使用方法,本文使用的是最新 VisualStudio2019 的功能,也许在你看到这篇博客的时候这个版本已经过时 本文将会按照从简单到复杂, ...

  8. HDU 2068 RPG错排 [错排公式]

    1.题意:1到N的序列的排列中,元素位置与元素值相对应的情况(值为i的元素在某个排列中正好排在第i个位置)大于等于序列规模一半的情况,有多少个? 2.输入输出:每组数据一个数,N,规定输入以0结尾: ...

  9. 【Spring Cloud 源码解读】之 【这也太神奇了,RestTemplate加上一个@LoadBalanced注解就能实现负载均衡!】

    前提概要: 前天,有个前端大佬问了我两个问题:为啥不引入Ribbon依赖就能使用Ribbon?为啥RestTemplate加上@LoadBalanced注解就能负载均衡了?我也表示很疑惑,而我自己其实 ...

  10. django框架(1)

    一什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有的 ...