UVALive-7392 - Bundles of Joy【树型DP】【深搜】【好题】
来源:互联网 发布:python 3程序开发指南 编辑:程序博客网 时间:2024/04/30 19:10
UVALive-7392 - Bundles of Joy
题目链接:7392
题目大意:给出n种蛋糕,m家店。然后是m行,每行给出每家店买的蛋糕种类以及,买下这家店所有蛋糕的价格。问,怎么能用最少的钱买到n种蛋糕?
已知,A,B两家店蛋糕的种类满足
A完全包含B (B中有的蛋糕种类A中全有)A完全不包含B (B中有的蛋糕种类,A全没有)
注意:可能存在AB两家店卖的蛋糕是一样的,这时候需要选择价格低的那家
题目思路:首先建树,如图所示,头结点为所以得蛋糕种类。
然后从底部向上树形dp即可,
如果该节点的子节点组成的数组等于该节点,则更新该节点的dp值为两者最小值否则,该节点的dp值为该节点的val值
以下是代码:
#include <iostream>#include <iomanip>#include <fstream>#include <sstream>#include <cmath>#include <cstdio>#include <cstring>#include <cctype>#include <algorithm>#include <functional>#include <numeric>#include <string>#include <set>#include <map>#include <stack>#include <vector>#include <queue>#include <deque>#include <list>using namespace std;#define INF 1000000000struct node{ int id,val; vector <int> s; vector <int> child;}p[10005];int dp[100005];int vis[1005][1005];map <vector<int> ,int> mp;void init(){ mp.clear(); memset(dp,0,sizeof(dp)); memset(vis,0,sizeof(vis)); //记录第i个点第j个蛋糕是否可买 for (int i = 0; i < 10004; i++) { p[i].id = 0; p[i].val = 0; p[i].child.clear(); p[i].s.clear(); }}bool cmp(node a,node b){ if (a.s.size() != b.s.size()) return a.s.size() < b.s.size(); else return a.id > b.id;}bool cmp2(node a,node b){ return a.id < b.id;}void solve(int r){ int len = p[r].child.size(); if (len == 0) //如果没有儿子 { dp[r] = p[r].val; return; } int sumchild = 0; vector <int> a; //记录所有儿子的值 for (int i = 0; i < len; i++) { int cld = p[r].child[i]; solve(cld); //搜儿子 a.insert(a.end(),p[cld].s.begin(),p[cld].s.end()); //将所有儿子的值合并到一个数组中。 sumchild += dp[cld]; //把儿子的权值加在一起 } sort(a.begin(),a.end()); sort(p[r].s.begin(),p[r].s.end()); if (p[r].s == a) //如果儿子能代替该父节点(eg:儿子:1,2,345; 父亲: 12345) { dp[r] = min(p[r].val,sumchild); } else { dp[r] = p[r].val; }}int main(){ int t; cin >> t; while(t--) { int n,m; cin >> m >> n; init(); //初始化 p[0].id = 0; //设置头结点 for (int i = 1; i <= m; i++) { p[0].s.push_back(i); //头结点的s数组值为全部的蛋糕编号 vis[0][i] = 1; } p[0].val = INF; int tmp = 0; for (int i = 1,j = 1; j <= n; i++,j++) { cin >> p[i].val; int k; cin >> k; p[i].s.clear(); memset(vis[i],0,sizeof(vis[i])); while(k--) { int num; cin >> num; p[i].s.push_back(num); vis[i][num] = 1; } p[i].id = i; //去重,如果该数组出现过,则与之前进行比较,记录下花费较小值。 if (!mp[p[i].s]) mp[p[i].s] = i; else { p[mp[p[i].s]].val = min(p[i].val,p[mp[p[i].s]].val); i--; tmp++; //记录删去了几个点 } } n -= tmp; //找第i个结点的父节点 sort(p,p + n + 1,cmp); for (int i = 0; i < n; i++) { for (int j = i + 1; j <= n; j++) { int ok = 1; for (int k = 0; k < p[i].s.size(); k++) //遍历第i个店的所有蛋糕编号 { int no = p[i].s[k]; if (vis[p[j].id][no] == 0) //如果第j个店不全部包括第i个店的所有蛋糕 { ok = 0; break; } } if (ok) { p[j].child.push_back(p[i].id); //第j这个店的儿子是x这个店,注意存的是i的id值而不是i break; } } } sort(p,p + n + 1,cmp2); solve(0); cout << dp[0] << endl; } return 0;}/* 100 4 3 20 2 1 2 20 2 3 4 38 4 1 2 3 4 2 3 5 1 1 10 2 1 2 4 1 2 2 2 1 1 1 5 2 2 1 1 2 2 1 1 1 1 1 4 4 10 2 1 2 5 2 3 4 10 2 3 4 38 1 1 10 5 195 2 3 7 1113 2 4 5 99 1 8 4510 2 2 3 345 10 1 2 3 4 5 6 7 8 9 10 10 5 195 4 1 3 6 7 234 6 2 4 5 8 9 10 1000 10 1 2 3 4 5 6 7 8 9 10 10 2 1 3 10 2 6 7 */
1 0
- UVALive-7392 - Bundles of Joy【树型DP】【深搜】【好题】
- UVALive 7392 Bundles of Joy【bitset】【类树形DP】【杂题】
- UVA 7392 Bundles of Joy(乱搞)
- Bundles of Joy
- Bundles of Joy
- joy of data
- A Lot of Joy
- UVALIVE 7505 Hungry Game of Ants DP
- The Joy of Clojure 笔记
- UVALive - 4260 Fortune Card Game (DP&状态转移)好题
- UVALive-7304 - Queue of Soldiers 【动态规划】【组合函数】【好题】
- UVALive 4015 Caves(树型dp)
- Realms Of Joy - Time Of Light.
- joy
- UVALive - 7484 Association for the Country of Mububa(dp)
- 【UVALive 7505】Hungry Game of Ants(DP)
- Joy of SAX:Visual Basic 的示例
- The Joy of Living 生活的乐趣
- JavaMail--基础类详解
- JDBC基础应用(数据库增删改查)
- 在VS2015中用C++创建MFC规则动态库DLL
- dl4j基本环境搭建(win7+64位jdk1.8+IDEA)
- laravel 社区 使用ModelFactory 生产测试数据 artisan 建表
- UVALive-7392 - Bundles of Joy【树型DP】【深搜】【好题】
- "两地三中心"的容灾解决方案
- Effective Modern C++ 条款2 理解auto类型推断
- K sum算法
- 占位符
- java面试题训练0807_字符串逆转及回文
- Android UI(CheckBox)详解
- java学习之路 之 高级类特性1-instanceof操作符、对象类型转换(造型)
- SpringMVC 无法获取连接报错