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< ...
随机推荐
- Spring Boot Thymeleaf 使用详解
在上篇文章Spring Boot (二):Web 综合开发中简单介绍了一下 Thymeleaf,这篇文章将更加全面详细的介绍 Thymeleaf 的使用.Thymeleaf 是新一代的模板引擎,在 S ...
- python模块之random模块
random模块 随机模块,用于处理随机问题. import random # 随机整数 print(random.randint(0, 9)) # 0到9之间随机一个整数 print(random. ...
- Vue打包文件放在服务器,浏览器存在缓存问题的解决
在入口文件index.html添加 <meta http-equiv="pragram" content="no-cache"> <meta ...
- JavaMail转发邮件
最近要做一个邮件转发功能,看了好多blog,都是接受邮件,再解析邮件内容,再组装成新的邮件发出! 我按照这个不够,不错!邮件发出去了.但是好麻烦啊,接受邮件是个Message,发送邮件也是个Messa ...
- Qt3升至Qt4需要注意的几件事项浅谈
Qt3升至Qt4需要注意的几件事项浅谈 公司以前的项目是用Qt3写的,随着时间的推移慢慢显示出Qt3有多方面的限制,因此先公司决定用Qt4来改写这个项目,并为软件添加新功能,在此背景先编写此文章. 先 ...
- CITRIX ADC配置SSL卸载
如上图,将ssl的加密解密放在前端的负载均衡设备上,客户端到VPX的访问都是加密的,VPX到后端的服务器都是http的 Step1:上传证书到VPX,如下图: Step2:创建SSL的虚拟服务器并且绑 ...
- 深入谷歌和甲骨文旷日持久的版权战争,趣味科普当前最火的编程语言JAVA的前世今生
这篇文章是我在B站上投稿的一个科普java的视频文案,内容如标题,感兴趣的码农朋友可以移步观看https://www.bilibili.com/video/av81171108/ 在过去短短几十年间, ...
- DOCKER学习_003:Docker的存储
一 简介 docker提供数据卷来实现数据共享与持久化,而数据卷的挂载有两种方式: 挂载主机目录(Bind mounts) 数据卷容器(Data Volumes) 数据卷是一个可供容器使用的特殊目录, ...
- GNE: 4行代码实现新闻类网站通用爬虫
GNE(GeneralNewsExtractor)是一个通用新闻网站正文抽取模块,输入一篇新闻网页的 HTML, 输出正文内容.标题.作者.发布时间.正文中的图片地址和正文所在的标签源代码.GNE在提 ...
- 【题解】P5446 [THUPC2018]绿绿和串串(manacher)
[题解]P5446 [THUPC2018]绿绿和串串(manacher) 考虑对于一个串进行\(f\)操作,就是让他变成一个以最后一个节点为回文中心的回文串. 那么对于某个位置\(p\),假如它是一个 ...