dp day1

题目描述:

在M公司里,每个人只有一个直属上司(除了boss)。这个公司举办派对,每个人可以给派对带来一定的欢乐值,但是每个人不能和自己的上司同时参加这个派对,求派对的最大欢乐值。

输入:

      第一行n表示公司有n个人。

第二行n个数,表示每个人的上司是谁,如果这个人的上司为0,说明这个人是boss。

      第三行n个数,表示每个人的欢乐值为wi。

输出:

一行一个数表示最大欢乐值

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;

const int maxn=1000005;

int n,w[maxn],head[maxn],tov[maxn],nxt[maxn];

int tot=0,boss;

int dp[maxn][2],f[maxn];

void add(int u,int v)
{
	tot++;
	tov[tot]=v;
	nxt[tot]=head[u];
	head[u]=tot;
}

void dfs(int u,int fa)
{
	for (int i=head[u];i;i=nxt[i])
	{
		int v=tov[i];
		if (v==fa)
		continue;
		dfs(v,u);
		dp[u][0]+=max(dp[v][0],dp[v][1]);
		dp[u][1]+=dp[v][0];
	}
}

int main()
{
	freopen("party.in","r",stdin);
	freopen("party.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		int to;
		scanf("%d",&to);
		add(to,i);
		if (to==0)
		boss=i;
	}
	for (int i=1;i<=n;i++)
	   scanf("%d",&w[i]);
	for (int i=1;i<=n;i++)
	   dp[i][1]=w[i];
	dfs(boss,0);
	f[boss]=max(dp[boss][1],dp[boss][0]);
	printf("%d\n",f[boss]);
	return 0;
}

01背包问题 1表示取0不取从叶子节点往上更新

题目描述:

            给定两个长度为n的排列p1和p2,求它们的最长公共子序列。

输入:

            第一行一个数n。

接下来两个n个数分别表示p1和p2。

输出:

            一个数表示最长子序列的长度。

样例输入:

3

123

213

样例输出:


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=100005;

int n;

int f[maxn],a[maxn],b[maxn],belong[maxn],g[maxn];

int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		belong[a[i]]=i;
	}
    for (int i=1;i<=n;i++)
       scanf("%d",&b[i]);
    for (int i=1;i<=n;i++)
    	g[i]=belong[b[i]];
    int len=0;
    for (int i=1;i<=n;i++)
    {
    	if (g[i]>f[len])
    	  f[++len]=g[i];
    	else
    	{
    		int x=lower_bound(f+1,f+len+1,g[i])-f;
    		f[x]=g[i];
    	}
    }
    printf("%d\n",len);
    return 0;
}

求一个最长上升序列

小a可以攻打m座城堡,攻打每个城堡有不同的宝物,但是在攻打有些城堡前,需要攻打另外的城堡。小a想知道,能获得的最多宝物是多少?

输入:

第一行两个数,n,m。分别表示有n个城堡,可以攻打m个。

接下来n行每行两个数a,b,分别表示在攻打第i个城堡前需要攻打a,攻打后获得b的宝物。

输出:

一行一个数ans表示可以获得的最大宝物数量。

样例输入1

ew Roman";mso-hansi-font-family:"Times New Roman"'>样例输出:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=505;

int dp[maxn][maxn],size[maxn],head[maxn],nxt[maxn],tov[maxn],w[maxn];

int n,m,tot=0;

void add(int u,int v)
{
	tot++;
	tov[tot]=v;
	nxt[tot]=head[u];
	head[u]=tot;
}

void dfs1(int u)
{
	size[u]=1;
	for (int i=head[u];i;i=nxt[i])
	{
		int v=tov[i];
		dfs1(v);
		size[u]+=size[v];
	}
}

void dfs(int u)
{
	for (int i=head[u];i;i=nxt[i])
	{
		int v=tov[i];
		dfs(v);
		int minu=min(size[u],m);
		for (int j=minu;j>=1;j--)
	       for (int k=0;k<=min(j-1,size[v]);k++)	
		      dp[u][j]=max(dp[u][j-k]+dp[v][k],dp[u][j]);
	}
}

int main()
{
	freopen("treasure.in","r",stdin);
	freopen("treasure.out","w",stdout);
	scanf("%d%d",&n,&m);
	m++;
	for (int i=1;i<=n;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		w[i]=b;
		add(a,i);
	}
	for (int i=1;i<=n;i++)
	   dp[i][1]=w[i];
	dfs1(0);
	dfs(0);
	printf("%d\n",dp[0][m]);
	return 0;
}   
一个分组dp


猜你喜欢

转载自blog.csdn.net/beloved_rancy/article/details/79371980