标签:p12 using return 背包 img ret dfs bre define
1.codeforces 816 E. Karen and Supermarket
题意:有n件商品,每件有价格ci,优惠券di,对于i>=2,使用di的条件为:xi的优惠券需要被使用,问初始金钱为b时 最多能买多少件商品? n<=5000,ci,di,b<=1e9
思路:
根据限制连边 转化为背包问题
dp[i][j][0/1] 表示以i为根的树中选了j件,第i件打不打折的最优值。
转移时枚举儿子选了多少 他就选了j减多少
最后统计答案 第一个小于等于限制钱数的就是。
#include<iostream> #include<cstdio> #include<cstring> #define N 5007 #define inf 0x3f3f3f3f using namespace std; int n,b,ans,cnt,x; int head[N],dp[N][N][2],siz[N],pr[N],pd[N]; struct edge { int v,next; }e[N<<1]; inline int read() { int x=0,f=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } inline void add(int u,int v) { e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt++; } void dfs(int u) { siz[u]=1; dp[u][0][0]=0; dp[u][1][0]=pr[u]; dp[u][1][1]=pr[u]-pd[u]; for(int i=head[u];~i;i=e[i].next) { int v=e[i].v; dfs(v); for(int j=siz[u];j>=0;j--) { for(int k=1;k<=siz[v];k++) { dp[u][j+k][0]=min(dp[u][j+k][0],dp[u][j][0]+dp[v][k][0]); dp[u][j+k][1]=min(dp[u][j+k][1],dp[u][j][1]+dp[v][k][0]); dp[u][j+k][1]=min(dp[u][j+k][1],dp[u][j][1]+dp[v][k][1]); } }siz[u]+=siz[v]; } } int main() { n=read();b=read(); memset(dp,0x3f,sizeof dp); memset(head,-1,sizeof head); for(int i=1;i<=n;i++) { pr[i]=read();pd[i]=read(); if(i!=1) { x=read();add(x,i); } }dfs(1); for(int i=n;i>=0;i--) { if(dp[1][i][1]<=b || dp[1][i][0]<=b) { ans=i; break; } } printf("%d\n",ans); return 0; }
2.洛谷P1272
题意:一棵树上要断掉大小为P的子树,求最少断掉边数
思路:
显然树形dp
dp[i][j]:i为根断掉子树大小为j最小边数
初始化dp[u][1]=1的度数
转移时枚举当前点断掉多少,算出连到的儿子断掉多少
因为由儿子转移过来,他们之间的连边不能断
但是转移时断掉了两次,所以答案减2
#include<iostream> #include<cstdio> #include<cstring> #define N 151 #define inf 0x7f7f7f7f using namespace std; int dp[N][N],head[N],d[N]; int n,m,ans,cnt; struct node { int u,v,next; }e[N<<1]; inline int read() { int x=0,f=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } inline void add(int u,int v) { e[++cnt].v=v;e[cnt].next=head[u];head[u]=cnt; } void dfs(int u,int fa) { dp[u][1]=d[u]; for(int i=head[u];i;i=e[i].next) { if(e[i].v!=fa) { dfs(e[i].v,u); for(int j=m;j>=1;j--) for(int k=1;k<=j;k++) dp[u][j]=min(dp[u][j],dp[e[i].v][k]+dp[u][j-k]-2); } }ans=min(ans,dp[u][m]); } int main() { int x,y; memset(dp,1,sizeof dp); n=read();m=read(); for(int i=1;i<n;i++) { x=read();y=read(); add(x,y);add(y,x); d[x]++;d[y]++; } ans=inf; dfs(1,0); printf("%d\n",ans); return 0; }
标签:p12 using return 背包 img ret dfs bre define
原文地址:http://www.cnblogs.com/L-Memory/p/7470228.html