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

版权声明:本文为博主原创文章,转载请务必注明出处。 https://blog.csdn.net/wlx65003/article/details/52144968

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

*/

猜你喜欢

转载自blog.csdn.net/wlx65003/article/details/52144968
今日推荐