您的位置:首页 > 其它

UVALive 7392 Bundles of Joy【bitset】【类树形DP】【杂题】

2016-08-07 21:16 555 查看

source

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=710&page=show_problem&problem=5414

Regionals 2015 :: North America - Rocky Mountain

思路

就是说去买蛋糕,有几个套餐,套餐间互不相交,问你最少花多少钱能吃到所有蛋糕。

因为套餐间互不相交,所以可以把所有套餐按包含关系建立一棵树,然后在树上按dfs序计算(类DP):

每个节点用一个bitset记录该套餐包含了哪些蛋糕。

然后对每个节点,遍历所有子节点,或在一起,如果1的个数少于当前节点,说明有蛋糕不能通过子套餐凑出来,那么答案就是当前节点的prize;如果1的个数等于当前节点,答案就是当前节点的prize和子节点prize的和取最小值。

建树的过程比较负载,有很多小细节需要注意,被坑了好久。

AC代码

#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>
#include <bitset>
//#include <unordered_map>
using namespace std;
#define CLR(x,y) memset((x),(y),sizeof(x))
typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 lll;

const int INF = 0x3f3f3f3f;
const int N = 110;
struct node
{
bitset<N>st;
int prize = 0;
vector<node*>son;

bool vis = 0;
node() {}
node(bitset<N>&_st, int _prize)
{
st = _st;
prize = _prize;
}
~node()
{
for (auto &v : son)
{
delete v;
}
}
};

void insert(node *u, bitset<N>&st, int prize)
{
bool down = 0, up = 0;
for (auto &v : u->son)
{
if ((st | (v->st)) == (v->st))
{
down = 1;
insert(v, st, prize);
break;
}
if ((st | (v->st)) == st)
{
up = 1;
break;
}
}
node *t = new node(st, prize);
if (up)//如果有节点被他包含
{
for (auto ite=u->son.begin() ; ite!=u->son.end() ;)//把所有被包含的节点移动到他下面
{
if((((*ite)->st)|st)==st)
{
t->son.push_back(*ite);
ite=u->son.erase(ite);
}
else ite++;
}
u->son.push_back(t);
}
else if (down == 0)//独立
{
u->son.push_back(t);
}
}

int dfs(node *u)
{
if (u->vis) return u->prize;
bitset<N> temp;
int sum = 0;
for (auto &v : u->son)
{
temp |= (v->st);
sum += dfs(v);
}
u->vis = 1;
if (temp == u->st)
{
u->prize = min(u->prize, sum);
}
return u->prize;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int n, m;
scanf("%d%d", &n, &m);
bitset<N>temp_set;
for(int i=1 ; i<=n ; ++i)
{
temp_set[i]=1;
}
node* root = new node(temp_set, INF);
for (int i = 0; i < m; ++i)
{
int p, s;
scanf("%d%d", &p, &s);
bitset<N>status;
for (int i = 0; i < s; ++i)
{
int temp;
scanf("%d", &temp);
status[temp] = 1;
}
insert(root, status, p);
}
printf("%d\n", dfs(root));
delete root;
}
return 0;
}
/*
4
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

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm