传送门:QAQQAQ

题意:商店里有N种药水,每种药水都有一个售价和回收价。小S攒了V元钱,还会M种魔法,可以把一些药水合成另一种药水。他一天可以使用K次魔法,问他一天最多赚多少钱?

N<=60 M<=240

V<=1000

k<=30

思路:这是一道比较有技术含量的DP题。

我们定义$dp[i][j]$为消耗了$i$个金币(金币不能回收),使用了$j$次魔法能得到的最多钱(最后求答案时注意要$dp[i][j]-i$)

在直接转移的过程中,我们无法知道使用的金币都花在了哪些药品上,各种魔法又都用了几次,直接枚举又不知如何下手,所以我们要定义辅助数组:

我们定义$cost[i][j]$为最终消耗了$j$次魔法,得到了药品$i$的最小花费,这样转移方程就很容易了:
$dp[i][j]=max(dp[i-cost[p][t]][j-t]+w[p])$

$cost[i][j]=min(\sum cost[magic[p].to[t]][r]) (\sum r=j-1)$

而在处理$cost[i][j]$时我们又遇到了一些难题:我们没法知道在得到$i$的魔法中每种原料到底用了几次,其“下层”的魔法各用了几次,所以我们要再开一个辅助数组

我们定义对于当前搜到的魔法$i$,$ant[t][r]$为前该魔法前$t$个物品使用了$r$次魔法的最小花费

我们可以通过$t$逐步增大来更新后面的$ant$,其中$cost$和$ant$数组是互相利用的。

(在代码实现方面,要注意$init$函数里的循环顺序,一定要先枚举使用魔法数,这样才能保证在当前枚举到魔法数$j$时前面所有比$j$小的$ant$,$cost$数组已经最优化,这样就可以无忧无虑地转移啦~~)

代码:(用刷表写的,之前刷表越界了。。。)

#include<bits/stdc++.h>
using namespace std;
const int inf=(int)1e9; int cost[][],dp[][],ant[][];
int n,m,v,k;
int b[],s[];
struct node{
int from,len;
int to[];
}E[]; void checkmax(int &x,int y)
{
if(x<y) x=y;
} void checkmin(int &x,int y)
{
if(x>y) x=y;
} void init()
{
for(int i=;i<=n;i++)
{
for(int j=;j<=k;j++) cost[i][j]=b[i];
}
for(int j=;j<=k;j++)
{
for(int i=;i<=m;i++)
{
for(int t=;t<=E[i].len;t++)
{
for(int r=;r<=j-;r++)
{
ant[t][r]=inf;
for(int p=;p<=r;p++) checkmin(ant[t][r],ant[t-][p]+cost[E[i].to[t]][r-p]);
}
}
checkmin(cost[E[i].from][j],ant[E[i].len][j-]);
}
}
} void solve()
{
memset(dp,,sizeof(dp));
for(int i=;i<=v;i++)
{
for(int j=;j<=k;j++)
{
for(int t=;t<=n;t++)//新加药水种类
{
for(int p=;p<=k-j;p++)//新用魔法次数
{
if(i+cost[t][p]>v||j+p>k) continue;
checkmax(dp[i+cost[t][p]][j+p],dp[i][j]+s[t]);
}
}
}
}
int ans=;
for(int i=;i<=v;i++)
{
for(int j=;j<=k;j++) checkmax(ans,dp[i][j]-i);
}
cout<<ans<<endl;
} int main()
{
scanf("%d%d%d%d",&n,&m,&v,&k);
for(int i=;i<=n;i++) scanf("%d%d",&b[i],&s[i]);
for(int i=;i<=m;i++)
{
scanf("%d",&E[i].from);
scanf("%d",&E[i].len);
for(int j=;j<=E[i].len;j++) scanf("%d",&E[i].to[j]);
}
init();
solve();
return ;
}

洛谷P1860——新魔法药水的更多相关文章

  1. 洛谷P1860 新魔法药水

    洛谷题目链接 动态规划: 这个题目调了我好久....结果循环变量写错了... 而且题目有个坑!!!只能用开始给你的$v$元买入东西 回归正题: 我们定义状态$ans[i][j]$表示第$i$个物品用了 ...

  2. 洛谷P1242 新汉诺塔(dfs,模拟退火)

    洛谷P1242 新汉诺塔 最开始的思路是贪心地将盘子从大到小依次从初始位置移动到目标位置. 方法和基本的汉诺塔问题的方法一样,对于盘子 \(i\) ,将盘子 \(1\to i-1\) 放置到中间柱子上 ...

  3. 洛谷 P1305 新二叉树

    P1305 新二叉树 题目描述 输入一串完全二叉树,用遍历前序打出. 输入输出格式 输入格式: 第一行为二叉树的节点数n. 后面n行,每一个字母为节点,后两个字母分别为其左右儿子. 空节点用*表示 输 ...

  4. Luogu P1860 新魔法药水

    题目大意 具体题面及输入格式戳我! 商店里有\(N\)种药水,每种药水都有一个售价和回收价. 小\(S\) 攒了\(V\)元钱,还会\(M\)种魔法,可以把一些药水合成另一种药水. 他在第一天可以购买 ...

  5. 洛谷 P1305 新二叉树 Label:字符串的输出总是有惊喜

    题目描述 输入一串完全二叉树,用遍历前序打出. 输入输出格式 输入格式: 第一行为二叉树的节点数n. 后面n行,每一个字母为节点,后两个字母分别为其左右儿子. 空节点用*表示 输出格式: 前序排列的完 ...

  6. 洛谷P1242 新汉诺塔

    传送门啦 首先要将第n个盘子从x到y,那么就要把比n小的盘子全部移到6-x-y,然后将n移到y 仔细想想:6代表的是3根初始柱,3根目标柱. 6-(x+y) 便是我们的中转柱了,因为到这个位置是最优的 ...

  7. 洛谷P1242 新汉诺塔 【神奇的递归】

    题目描述 设有n个大小不等的中空圆盘,按从小到大的顺序从1到n编号.将这n个圆盘任意的迭套在三根立柱上,立柱的编号分别为A.B.C,这个状态称为初始状态. 现在要求找到一种步数最少的移动方案,使得从初 ...

  8. [P1860]新魔法药水

    题目描述 商店里有N种药水,每种药水都有一个售价和回收价.小S攒了V元钱,还会M种魔法,可以把一些药水合成另一种药水.他一天可以使用K次魔法,问他一天最多赚多少钱? 输入输出格式 输入格式: 第一行四 ...

  9. 洛谷 [P4301] 新Nim游戏

    线性基 +博弈论 先手必胜当且仅当先手取完之后留下的序列无论如何组合,异或和都不为 0 也就是剩下的整数线性无关,所以我们对所有整数排序,由高往低的贪心的插入线性基, 无法插入的就有先手取出,容易发现 ...

随机推荐

  1. Linux环境下安装PHP的gd库

    当前使用的安装包版本: freetype-2.4.0.tar.bz2 jpegsrc.v9.tar.gz libpng-1.6.28.tar.gz 1.安装freetype tar jxvf free ...

  2. delphi INI文件

    INI 文件读写 filecreate('路径加文件名')://创建一个文件. (1) INI文件的结构: ;这是关于INI文件的注释部分 [节点] 关键字=值 ... INI文件允许有多个节点,每个 ...

  3. WebKit资源

    WebKit 资料搜集 1 what is webkit? WebKit 是一个开源浏览器网页排版引擎,与之相应的引擎有Gecko(Mozilla,Firefox 等使用的排版引擎)和Trident( ...

  4. python正则re

    import reline = "Catsaresmarterthandogs"matchObj = re.match( r'(.*)are(\w{2})(.*)', line, ...

  5. linux进阶之路(三):vi/vim编辑器

    所有Linux都会内置vi,vim是vi的增强版本,被誉为"编辑之神",玩转vim可以让你完全脱离鼠标. vim可以分为两种模式: 普通模式:使用vim 文件名,进入普通模式.普通 ...

  6. Xen的半虚拟化(Paravirtualization)

    三个特权级 IA-32体系提供了4个特权级别,正常情况下只用了2个, 操作系统运行在Ring 0,而应用程序运行在Ring 3. Xen让自己运行在Ring 0, 而操作系统运行在Ring 1, 应用 ...

  7. CSS中复选框单选框与常用12px文字不对齐问题(转载)

    原文  http://www.cnblogs.com/aobingyan/p/3823556.html,有删改 目前中文网站上面的文字,绝大多数网站的主流文字大小为12px,因为在目前高分辨率显示器屏 ...

  8. 内网渗透_win_socks代理_reGeorg+proxifier

    遇到内网windows机器,如果想远程登陆,通常得通过代理,常用的nc.lcx 工具可满足要求. 如 lcx 示例: 两台机器上均上传lcx.exe 在 xp机器(公网)上执行 lcx.exe -li ...

  9. 关于EntityFramework 更新数据记录时字段全部更新问题和不从数据库中获取直接更新记录

    一.一直对这个比较疑惑感觉只修改一条数据记录的一个字段结果更新Savechages后跟踪生成sql竟然是全部被修改,感觉微软怎么这么傻,总觉得会有其它方式可以只更新部分字段,但一直没有找到相关设置,最 ...

  10. 内网端口转发[SSH]

    一.应用场景 获取到目标边界机器linux服务器一台,想继而向内网其他机器渗透,获取到一台webshell发现处于内网当中且不通外网.可以通过linux ssh隧道对目标内网机器进行访问. 二.利用手 ...