2016 UESTC Training for Dynamic Programming F - 柱爷与三叉戟不得不说的故事 压位dp
来源:互联网 发布:dmx控制器淘宝 编辑:程序博客网 时间:2024/05/13 17:40
F - 柱爷与三叉戟不得不说的故事
Time Limit: 500/500MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
在喵蛤蛤城,人人都知晓柱爷有一把传奇武器三叉戟
.据传,这是一位在$772002$年前陨落的强大守护者F91曾经使用过的12级灵能武器,
拥有毁天灭地的力量
但只有很少人知道当柱爷获得三叉戟时,三叉戟的力量已经消失殆尽.为了能修复三叉戟的力量,柱爷苦心专研
古籍,发现只有找到最神秘的15种元素,将元素的力量重新注入到三叉戟中,三叉戟就能恢复到原来的力量,
于是柱爷踏上了寻找神秘元素的旅行.
柱爷首先发现15个由卿学姐掌控的地牢,里面正好有15种对应元素.冷静的柱爷没有贸然行动,经过一番详细的打听,
柱爷得知了第i种元素需要Di的精力去获得;与此同时,柱爷还发现了由白学潘看守的N个洞穴,第i个洞穴中
有Ai个不同的元素,分别是B1,B2,...,B Ai,需要Ci的精力去获得.
同种元素不得拥有多个,不然元素之间会产生强大的斥力,会发生爆炸;不能攻下一个洞穴后,留有元素不拿走,
元素可能会辐射,伤害喵哈哈村的大爷......
但是柱爷岂是凡人?柱爷修复三叉戟时花费的总是最小的精力!
那么这个最小的花费是多少呢?
Input
第一行包括15个正整数,第i个数表示Di.
第二行包括一个整数表示N.
接下来N行,每行有一个整数表示Ai,后面紧接着Ai个不同的正整数,最后又一个正整数Ci表示需要花费的精力.
数据保证:
0 <= N <= 10000
1 <= Di <= 20000
0 <= Ai <= 5
1 <= Ci <= 2000000
Output
输出一个整数ans:
表示至少花ans的精力去修复三叉戟.
Sample input and output
9599 11186 3513 3112 19106 1171 4254 4786 11880 19550 4793 17049 10779 11096 971354 10 1 8 11 12126453 14 9 15 16555603 7 3 14 11612625 13 5 9 2 11 7105120 980331
141587
Source
2016 UESTC Training for Dynamic Programming
My Solution
压位dp
dp[i] 表示状态为i是的最小消费, 状态i则是i的二进制表示以后哪些地方是1表示有已经获得了哪些元素
Ind = 1<<0, 表示有元素 1;
Ind = 1<<15 表示有元素 15;
Ind = 0;
Ind += 1<<0;]
Ind += 1<<15;
然后Ind 表示有元素 1 、15;
然后有十五个元素, 所以最多1<<15, 设为 maxi = (1<<15) + 2;
然后
for(int i = 0; i < maxi; i++){
for(int j = i; j; j = (j - 1) & i){ //!这样就可以枚举了可能的子集了
dp[i] = min(dp[i], dp[j] + dp[j^i]);
}
}
就好了,dp[maxn]先初始化为 Inf = 1e9数量级的, memset(dp, 0x3f, sizeof dp);
然后输入的时候根据元素集合计算Ind , 保留min{dp[Ind};
然后从0 ~ maxi 所以状态,包括无效状态(就是并没有值输入, 为Inf的那些状态)一起转移;
最好Ind = 0, i = 0 ~ 15
Ind += 1<<i;
然后输出dp[Ind].
复杂度 O(1e7);
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn = 50000, maxi = (1<<15) + 2;int dp[maxn];int main(){ #ifdef LOCAL freopen("a.txt", "r", stdin); #endif // LOCAL int n, d, a, ai, c, Ind; memset(dp, 0x3f, sizeof dp); //cout<<(dp[0])<<endl; 1e9级的 //int l = 1e9; //cout<<l<<endl; for(int i = 0; i < 15; i++){ scanf("%d", &d); Ind = 1<<i; //cout<<Ind<<endl; dp[Ind] = d; } scanf("%d", &n); while(n--){ Ind = 0; scanf("%d", &a); for(int i = 0; i < a; i++){ scanf("%d", &ai); Ind += (1<<(ai-1)); //!WA5 用 1<<0 表示有 元素 1 的 } scanf("%d", &c); if(Ind != 0) dp[Ind] = min(dp[Ind], c); //WA5 不是test5 触发的Bug 但如果 a == 0, 就是什么也没有 好吧, 没什么影响有效的是1开始的 } for(int i = 0; i < maxi; i++){ for(int j = i; j; j = (j - 1) & i){ //!这样就可以枚举了可能的子集了 dp[i] = min(dp[i], dp[j] + dp[j^i]); } } Ind = 0; for(int i = 0; i < 15; i++) Ind += (1<<i); printf("%d", dp[Ind]); return 0;}
Thank you!
- 2016 UESTC Training for Dynamic Programming F - 柱爷与三叉戟不得不说的故事 压位dp
- CDOJ 1355 柱爷与三叉戟不得不说的故事(枚举子集状压dp)
- 【cdoj 1335】柱爷与三叉戟不得不说的故事 状压dp+子集枚举
- 【CDOJ 1355】柱爷与三叉戟不得不说的故事 【状压DP+子集枚举】
- 2014 UESTC Training for Dynamic Programming F
- 2016 UESTC Training for Dynamic Programming D - 柱爷的恋爱 区间dp、记忆化搜索
- 2016 UESTC Training for Dynamic Programming A - 柱爷与咸鱼神功 0-1背包
- 2016 UESTC Training for Dynamic Programming(1)
- 2016 UESTC Training for Dynamic Programming C - 柱爷的下凡 预处理打表、背包问题
- 2016 UESTC Training for Dynamic Programming H - 柱爷大战滑稽王 LCS转LIS
- 2016 UESTC Training for Dynamic Programming P - 柱爷的矩阵 矩阵、递推
- 2016 UESTC Training for Dynamic Programming Q - 柱爷的宝藏 斜率优化
- 2016 UESTC Training for Dynamic Programming J - 柱爷抢银行II dp单调队列优化
- 2016 UESTC Training for Dynamic Programming L - 柱爷抢银行MkⅣ dp 线段树优化
- 2014 UESTC Training for Dynamic Programming
- 2014 UESTC Training for Dynamic Programming G
- 2014 UESTC Training for Dynamic Programming I
- 2014 UESTC Training for Dynamic Programming J
- 《页面制作》课程学习摘要
- telnet命令的安装
- Java 序列化机制(二) -- 控制序列化的兼容性
- RHEL7重定向和文件查找
- multimap用法
- 2016 UESTC Training for Dynamic Programming F - 柱爷与三叉戟不得不说的故事 压位dp
- RxJava源码初步分析
- 145. Binary Tree Postorder Traversal
- Task运行过程分析3——Map Task内部实现
- android studio 获得SHA1 码的步骤
- NYOJ squares(计算几何+区间覆盖)
- 数组引用与数组的一些小小小小研究
- 深入理解JVM03--垃圾收集器
- EventBus的使用与深入学习