题目描述:
在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