Zookeeper的Java API操作(一):创建、删除节点

Android入门视频教程!12年高级工程师的“飞升之路”,层层深入

  返回  

【算法与数据结构】——树形DP(1)

2021/8/20 12:31:29 浏览:

简介

在树形结构上实现的动态规划叫做树形DP。动态规划自身是多阶段决策问题,而树形结构有明显的层次性,正好对应动态规划的多个阶段。树形DP的求解过程一般为自底向上,将子树从小到大作为DP的“阶段”,将节点编号作为DP状态的第1维,代表以该节点为根的子树。树形DP一般采用深度优先遍历,递归求解每棵子树,回溯时从子节点向上进行状态转移。在当前节点的所有子树都求解完毕后,才可以求解当前节点。

别墅派对

题目地址HDU2412 别墅派对
题意:邀请员工聚会,除了大老板每个人都有一个唯一的老板(直接上司),当一个人被邀请时他的老板不会被邀请,请确定邀请客人的最大数量。另外,需要表明客人列表中的人是否是唯一确定的。
思路:本题属于最大独立集问题,和POJ2342/HDU1520类似,但增加了唯一性判断。
AC代码:

/*
**Author:skj
**Time:
**Function:
*/
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 205;
struct Edge{
    int to;
    int next;
};
int head[maxn];
Edge e[maxn];
int dp[maxn][2];//dp[u][0]表示不选择节点u时的最大员工数,dp[u][1]表示选择节点u时的最大员工数
int f[maxn][2];//f[u][0]表示不选择节点u时的方案唯一性,等于1则唯一,f[u][1]表示选择节点时的方案唯一性
map<string,int>ms;
int cnt;
void init(int n)
{
    for(int i = 1;i <= n;i++)
    {
        dp[i][0] = 0;
        dp[i][1] = 1;
    }
    memset(f,1,sizeof(f));
    ms.clear();
    cnt = 0;
}
void createMap(int n)//有向图建图
{
	for(int i = 1;i <= n;i++)
	{
		head[i] = -1;
	}
	memset(e,0,sizeof(e));
	string a, b;
	cin >> a;

	ms[a] = ++cnt;
	for(int i = 1;i <= n - 1;i++)
	{
	    cin >> a >> b;
		if(!ms.count(a))
        {
            ms[a] = ++cnt;
        }
        if(!ms.count(b))
        {
            ms[b] = ++cnt;
        }
		e[i].to = ms[a];
		e[i].next = head[ms[b]];
		head[ms[b]] = i;
	}
}
void DFS(int n)
{
    for(int u = head[n];u!=-1;u = e[u].next)
    {
        int v = e[u].to;
        DFS(v);
        if(dp[v][0]>dp[v][1])
        {
            dp[n][0]+=dp[v][0];
            if(!f[v][0])
            {
                f[n][0] = 0;
            }
        }
        else if(dp[v][0]<dp[v][1])
        {
            dp[n][0]+=dp[v][1];
            if(!f[v][1])
            {
                f[n][0] = 0;
            }
        }
        else
        {
            dp[n][0] += dp[v][0];
            f[n][0] = 0;
        }
        dp[n][1]+=dp[v][0];
        if(!f[v][0])
        {
            f[n][1] = 0;
        }
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
        init(n);
        createMap(n);
        DFS(1);
        dp[0][0] = max(dp[1][0],dp[1][1]);
        if(dp[1][0]>dp[1][1])
        {
            if(!f[1][0])
            {
                f[0][0] = 0;
            }
        }
        else if(dp[1][1]>dp[1][0])
        {
            if(!f[1][1])
            {
                f[0][0] = 0;
            }
        }
        if(dp[1][0]==dp[1][1])
        {
            f[0][0] = 0;
        }
        if(f[0][0])
        {
            printf("%d Yes\n",dp[0][0]);
        }
        else
        {
            printf("%d No\n",dp[0][0]);
        }
    }
    return 0;
}

战略游戏

题目地址POJ1463
题意:要放置士兵,看守城市道路,一个士兵可以看守所有与士兵所在节点相连的道路,问最少纺织多少士兵。
思路:跟上面的别墅派对基本一样

/*
**Author:skj
**Time:
**Function:
*/
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=1505;
vector<int> tree[N];
int dp[N][2];//dp[u][0]表示不在u点放置士兵最少放置士兵的数量,dp[u][1]表示在u点放置士兵最少放置士兵的数量
void init()
{
    for(int i = 0;i < N;i++)
    {
        tree[i].clear();
    }
}
void DFS(int n)
{
    dp[n][0] = 0;
    dp[n][1] = 1;
    for(int i = 0;i < tree[n].size();i++)
    {
        int v = tree[n][i];
        DFS(v);
        dp[n][1] += min(dp[v][0],dp[v][1]);
        dp[n][0] += dp[v][1];
    }
}
int main()
{
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
    int t;
    while(scanf("%d",&t)!=EOF)
    {
        int a, b,root = -1;
        init();
        for(int j = 1;j <= t;j++)
        {
            scanf("%d:(%d)",&a,&b);
            if(root == -1)
            {
                root = a;
            }
            for(int i = 1;i<=b;i++)
            {
                int x;
                scanf("%d",&x);
                tree[a].push_back(x);
            }
        }
        DFS(root);
        printf("%d\n",min(dp[root][0],dp[root][1]));
    }
    return 0;
}

工人请愿书

题目地址UVA12186
没找到原网址链接,只能贴一个Vjudge网站的链接了。
题意:给出一个树状关系图,公司里只有一个老板编号为0,其他人员从1开始编号。除了老板,每个人都有一个直接上司,没有下属的员工成为工人。
工人们想写一份加工资的请愿书,只有当不少于员工的所有下属的T%人递交请愿书后,该员工才会将请愿书递交给他的直接上级。输出能递交到老板处,最少需要多少工人写请愿书
思路:树形动态规划
代码:

/*
**Author:skj
**Time:
**Function:
*/
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N = 1e5+5;
vector<int> tree[N];
int dp[N];//dp[i]表示要第i号老板递交请愿书所需要的最少人数
bool comp(int a,int b)
{
    return dp[a] < dp[b];
}
void DFS(int n, int b)
{
    dp[n] = 0;
    if(!tree[n].empty())
    {
        for(int i = 0;i < tree[n].size();i++)
        {
            DFS(tree[n][i],b);
        }
        int m = ceil(int(tree[n].size())*b*1.0/100);
        sort(tree[n].begin(),tree[n].end(),comp);
        for(int i = 0;i < m;i++)
        {
            dp[n] += dp[tree[n][i]];
        }
    }
    else
    {
        dp[n]=1;
    }
}
int main()
{
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
    int a, b;
    while(scanf("%d%d",&a,&b)&&a)
    {
        for(int i = 1;i <= a;i++)
        {
            int x;
            scanf("%d",&x);
            tree[x].push_back(i);
        }
        DFS(0,b);
        printf("%d\n",dp[0]);
        for(int i = 0;i < N;i++)
        {
            tree[i].clear();
        }
    }
    return 0;
}

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号