题意:某电台要广播一场比赛,该电台网络是由n个网点组成的一棵树,其中m个点为客户端,其余点为转发站。客户端i愿支付的钱为p[i],每一条边需要的花费固定,问电台在保证不亏损的情况下,最多能使多少个客户端接收到信息?广播台所在的节点编号为1分析:树形DP1.用dp[u][j]表示从转发站u开始计算,满足其子树中j个顾客的最大收益 分析节点u的孩子节点v a.放弃该孩子v,值不变 b.取该孩子的若干的节点:dp[u][j-k]+dp[u][k]-cost[i][j](cost[i][j]为连通该边所需要付出的代价。)所以状态转移方程为:dp[u][j]=max(dp[u][j],dp[u][j-k Read More
posted @ 2012-08-14 20:51 To be an ACMan Views(227) Comments(0) Diggs(0)
比较综合的题目。题意:有n个物品,有两辆车载重分别是c1,c2.问需要多少趟(c1,c2一起运一次就算1趟)能把物品运完。n比较小,只有10,而且需要把所有物品全部运完,便想到状态压缩来保存状态。首先记录好所有的可行状态,对于状态state能一趟运完。然后再利用01背包,dp[j],表示已运的状态为j,如果状态j与state[i]不冲突,则可以从状态j运一趟变为j|state[i]。View Code #include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int n Read More
posted @ 2012-08-14 19:02 To be an ACMan Views(166) Comments(0) Diggs(0)
中文题,题意自己看树形DP将0设为根节点,总攻击数为m,背包容量应该是m+1(0点也看做城堡);基础的树形DP,自己推一下状态转移方程吧。View Code #include<stdio.h>#include<string.h>#include<vector>#include<algorithm>using namespace std;vector<int>edge[224];int dp[224][224];int p[224],m, n;void dfs(int u){ int i, j, k; dp[u][1]=p[u];//初 Read More
posted @ 2012-08-14 16:52 To be an ACMan Views(187) Comments(0) Diggs(0)
题意:一棵树,有n个结点,每个结点有w[i]个bug,有p[i]的brain。我从1号结点开始走,带着m个战士。1个战士可以消灭20个bugs如果我把某个结点的所有bug都消灭了我就能得到那个结点的brain。如果想攻击当前结点,那么必须先攻击了它的父结点(1号点除外)。注意:1. 其中当你攻占了当前结点,你可以分派人手,走向几个不同的子结点,去攻占更多。也就是说,不是单一的路径。2. 如果输入0个战士直接输出0,即使该洞bug数为0,要获得该洞brain值,也需要至少一人经过该洞穴(可以不停留),而用dfs计算会出现正值。本题数据小,节点100,如果数据大了尽量不要用vector,可能会超时 Read More
posted @ 2012-08-14 15:06 To be an ACMan Views(198) Comments(0) Diggs(0)
题意:给定一个面值Price, 1美分的硬币有c[1]个, 5美分的硬币有c[2]个,10美分的硬币有c[3]个,25美分的硬币有c[4]个,求用给定的硬币兑换Price面额的钱,并且要求硬币数最多,求出每种硬币得用多少个.题目关键:要保存路径,然后输出。我们用pre[j]表示最新更新j的那个状态,j-w[i]等状态,因为多重背包里有二进制压缩,有些状态转移1次纸币数量不一定只加了1,所以用num[j]表示状态转移到j加了多少张纸币。路径输出处理:memset(ans,0,sizeof(ans));for(i=m;i!=0;i=pre[i]) //用pre[j]把路径逆着走一边{ in... Read More
posted @ 2012-08-14 14:06 To be an ACMan Views(373) Comments(0) Diggs(0)
题意:有钱sum,给出n组选择,每种选择有m个物品w,要买物品先必须买盒子,物品价格为w[i],价值p[i]。然后给出每种选择的一些物品的价格还有价值求取得最大值。物品依赖于盒子。按照背包九讲的做法:先对每组选择里的所有物品进行0-1背包处理,但背包容量为(总容量-盒子容量);然后跟上一组的状态比较来决定这一组选择 是选还是不选,取其中的较大值。用dp[i][j]表示第i组背包容量为j时的最大价值。在转移状态之前当前组选择的初始化:for(j=0;j<q;j++)//q表示盒子的价格 dp[i][j]=-INF;//当钱<盒子价格时,无价值,注意不要赋值为0, 这题有 重量为0,但 Read More
posted @ 2012-08-14 13:09 To be an ACMan Views(199) Comments(0) Diggs(0)
题意:给你钱的价值和数量,求能在价值m以内能够拼出多少种钱数。View Code #include<stdio.h>#include<string.h>#include<algorithm>using namespace std;bool dp[120003];int w[101],c[101];int main(){ int n, m, i, j; while(~scanf("%d%d",&n,&m)) { if(!m&&!n)break; for(i=1;i<=n;i++) scanf(" Read More
posted @ 2012-08-14 09:51 To be an ACMan Views(187) Comments(0) Diggs(0)
题意:说有一个人去买m元的东西,有n种钱币,没种钱币的面额是w[i],个数是C[i],售货员每种钱币有无数多个。现在这个人想让交易的钱个数最少,即找回的和付出钱的张数,最少。多重背包+完全背包。买家:多重背包;售货员:完全背包;开两个数组,分别计算出买家,售货员每个面额的最少张数。最重要的是上界的处理。可以注意到,上界为maxw*maxw+m(maxw最大面额的纸币),也就是24400元。(网上的证明)证明如下:如果买家的付款数大于了maxw*maxw+m,即付硬币的数目大于了maxw,根据鸽笼原理,至少有两个的和对maxw取模的值相等,也就是说,这部分硬币能够用更少的maxw来代替。证毕。真 Read More
posted @ 2012-08-14 09:32 To be an ACMan Views(1082) Comments(0) Diggs(0)