加强版金明的预算方案
Posted liguanlin1124
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加强版金明的预算方案相关的知识,希望对你有一定的参考价值。
题面粘上:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己与用的很宽敞的房间。
更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要丌超过
N 元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件不附件,附件是从属
于某个件的,下表就是一些主件不附件的例子:
主件 附件
电脑 打印机,扫描仪书柜 图书
书桌 台灯,文具
工作椅 无
如果要买归类为附件的物品,必须先买该附件所属的件。每个主件可以有很多个附件。附件可能
有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的 N 元。于是,他把每件物品规定
了一个重要度,分为 5 等:用整数 1?5 表示,第 5 等最重要。他还从因特网上查到了每件物品的
价格(都是在 10 元以内)。他希望在丌超过 N 元(可以等于 N 元)的前提下,使每件物品的价格
不重要度的乘积的总和最大。
设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j1,j2,...,jk,则
所求的总和为:
v[j1]×w[j1]+v[j2]×w[j2]+...+v[jk]×w[jk]
请你帮助金明设计一个满足要求的购物单。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
加强之处:可以有附件的附件(结果我读错了,以为是原题)。
树形dp,很裸,但是卡常会很厉害,还有O(n^2)的dp很容易写成O(n^3)。
代码:
#include<cstdio> #include<algorithm> using namespace std; #define N 8050 int n,m; int v[N],p[N],hed[N],cnt; struct ED { int to,nxt; }e[2*N]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int dp[N][N]; int dfs(int u) { int ret = v[u]; dp[u][ret]=v[u]*p[u]; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; int now = dfs(to); if(j==hed[u]) { ret += now; for(int k = v[u];k<=ret;k++) { dp[u][k]=dp[to][k-v[u]]+v[u]*p[u]; } }else { for(int a = ret;a>=v[u];a--) { for(int b = 0;b<=now;b++) { if(a+b>n)break; if(dp[u][a+b]<dp[u][a]+dp[to][b])dp[u][a+b]=dp[u][a]+dp[to][b]; } } ret+=now; } } return ret; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d%d",&n,&m); for(int q,i=1;i<=m;i++) { scanf("%d%d%d",&v[i],&p[i],&q); ae(q,i); } dfs(0); int ans = 0; for(int i=1;i<=n;i++) { ans = max(ans,dp[0][i]); } printf("%d ",ans); fclose(stdin); fclose(stdout); return 0; }
从dalao那里学来的O(n^2)神奇dfs。
以上是关于加强版金明的预算方案的主要内容,如果未能解决你的问题,请参考以下文章