题意:

给你 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. html(四)数据库curd操作与分页查询

    数据库操作curd : 1.首先要建立项目处理好自己逻辑包: 其中util工具包中建立两个工具类 jdbc连接和page分页 DBUtil.java: db工具类就是用于连接数据库的jdbc架包,里面 ...

  2. Python--day61--Django项目配置相关

    static文件查找:

  3. 2019-1-4-win10-uwp-win2d-CanvasVirtualControl-与-CanvasAnimatedControl

    title author date CreateTime categories win10 uwp win2d CanvasVirtualControl 与 CanvasAnimatedControl ...

  4. win10 uwp 使用 Microsoft.Graph 发送邮件

    在 2018 年 10 月 13 号参加了 张队长 的 Office 365 训练营 学习如何开发 Office 365 插件和 OAuth 2.0 开发,于是我就使用 UWP 尝试使用 Micros ...

  5. H3C 查看设备路由表

  6. ASP.NET Core 开启后台任务

    本文告诉大家如何通过 Microsoft.Extensions.Hosting.BackgroundService 开启后台任务 实现 BackManagerService 类继承 Backgroun ...

  7. react + webpack 多页面搭建

    一.利用 creat-react-app 新建一个react单页面应用. cnpm i -g create-react-app create-react-app demo cd demo npm st ...

  8. vue-learning:28 - component - 组件事件的修饰符`.native / .sync`,以及组件属性`model`

    组件事件的修饰符.native / .sync,以及组件属性model .native 原生事件修饰符 在一个组件中,如果我们为其绑定一个原生的点击事件@click,基本是无效的. 在vue中对组件绑 ...

  9. [reviewcode] 那些基础comments

    多次提醒我,为变量取个合适的名字, so cute person: Not a big deal, but try using variable names better than my_sa 每个参 ...

  10. 它来了,它来了,centos 8 的时代到来了

    简介 Centos 8 已经在2019年9月24日正式发布.由于这是从Red Hat Enterprise Linux(RHEL)派生的Linux发行版,因此CentOS团队必须构建基础结构来支持新引 ...