hdu 4044 GeoDefense
来源:互联网 发布:阿历克斯梅森 知乎 编辑:程序博客网 时间:2024/05/21 20:53
//该题链接http://acm.hdu.edu.cn/showproblem.php?pid=4044
/* 报告人:SpringWater(GHQ)
//此题大意:一个以1为根节点的树,每个节点可以有修防御系统,每个节点的
防御系统(具有不同的价格和防御力)有chioce种可能的选择,敌人的基地为根节点,我方的基地为所有的叶
子节点,敌人可以随机发射一个攻击(具有一定的攻击力指数),当遇到你在某节点上修的防御拦截系统时,
它的攻击力会减去你该点的防御力,当它到达你的基地后经历了你所有的防御系统都还有剩余攻击力(即攻击
力为正值)的话,那你就输了!否则你就防御成功,题目要求,加入给你一定的money,问你能用这些钱所能
修建出最大的稳定防御力是多少(即敌人只要超过这个值就有可能将你打败);
解题思路:根据题意可判定是一个树形DP问题;即需算出每个点i,在给予j的钱,所能修建出的出的最大的稳定防御力;
即dp[i][j];所以再用最小背包解决即可;但此题的难点是,对于i来说他要求出的是在钱为j的前提下,最大攻击力,而对于孩子
来说,是求最大的最小防御力(听起来很别扭是吧!其实关键处理也在这里了!),这里的最小是指:当按照某种方式分配钱,来
修防御系统时,最薄弱(最小)的防御孩子是多少;而最大是指:在所有的方式中求得最大的那个最薄弱防御值,这就可以求得
不考虑i的情况下的dp[i][j]值,之后再在此基础上讨论i选择哪种拦截系统,这就是一个简单的背包dp问题了,故该题用了两次
dp来将问题简化是我觉得我最精华的部分了(嘻嘻!),动态方程如下:
第一次dp:在只讨论i的孩子dp[i][j]=max{(power<dp[i][j-price])?power:dp[i][j-price]} (涉及到既要利用dp[i][j],
又要初始化为0来求最大值,所以我就私自多用了一个temp[210]来中介)
第二次dp:只讨论i: dp[i][j]=max{dp[i][j],dp[i][j-price]+power}
回头感悟:虽然我这代码排在static的第二名,但是还是有几点不足,比如 (1)第二次dp就没有必要多用一个temp来
中转直接从最大money……0即可解决(2)在处理第一dp的时候,我花的时间太长,可能 是因为第一次独立编这种树
形dp吧,我想在今后的不断练习中,思维就更加成熟,编码就更加熟练!练习!练习!还是练习!噢!别忘了总结!嘻嘻!
*/
/* 报告人:SpringWater(GHQ)
//此题大意:一个以1为根节点的树,每个节点可以有修防御系统,每个节点的
防御系统(具有不同的价格和防御力)有chioce种可能的选择,敌人的基地为根节点,我方的基地为所有的叶
子节点,敌人可以随机发射一个攻击(具有一定的攻击力指数),当遇到你在某节点上修的防御拦截系统时,
它的攻击力会减去你该点的防御力,当它到达你的基地后经历了你所有的防御系统都还有剩余攻击力(即攻击
力为正值)的话,那你就输了!否则你就防御成功,题目要求,加入给你一定的money,问你能用这些钱所能
修建出最大的稳定防御力是多少(即敌人只要超过这个值就有可能将你打败);
解题思路:根据题意可判定是一个树形DP问题;即需算出每个点i,在给予j的钱,所能修建出的出的最大的稳定防御力;
即dp[i][j];所以再用最小背包解决即可;但此题的难点是,对于i来说他要求出的是在钱为j的前提下,最大攻击力,而对于孩子
来说,是求最大的最小防御力(听起来很别扭是吧!其实关键处理也在这里了!),这里的最小是指:当按照某种方式分配钱,来
修防御系统时,最薄弱(最小)的防御孩子是多少;而最大是指:在所有的方式中求得最大的那个最薄弱防御值,这就可以求得
不考虑i的情况下的dp[i][j]值,之后再在此基础上讨论i选择哪种拦截系统,这就是一个简单的背包dp问题了,故该题用了两次
dp来将问题简化是我觉得我最精华的部分了(嘻嘻!),动态方程如下:
第一次dp:在只讨论i的孩子dp[i][j]=max{(power<dp[i][j-price])?power:dp[i][j-price]} (涉及到既要利用dp[i][j],
又要初始化为0来求最大值,所以我就私自多用了一个temp[210]来中介)
第二次dp:只讨论i: dp[i][j]=max{dp[i][j],dp[i][j-price]+power}
回头感悟:虽然我这代码排在static的第二名,但是还是有几点不足,比如 (1)第二次dp就没有必要多用一个temp来
中转直接从最大money……0即可解决(2)在处理第一dp的时候,我花的时间太长,可能 是因为第一次独立编这种树
形dp吧,我想在今后的不断练习中,思维就更加成熟,编码就更加熟练!练习!练习!还是练习!噢!别忘了总结!嘻嘻!
*/
#include<stdio.h>#include<string.h>struct tree{ int k[60][2]; int son;}node[1010];//用于保存各节点的信息struct see{ int point; int next;}seek[2010];//用于索引个点的孩子int count[1010];//记录每个节点有多少种choiceint seek_num;int money;int dp[1010][210],temp[210];int add_son(int sta,int end)//建立索引表{ seek_num++; seek[seek_num].point=end; seek[seek_num].next=node[sta].son; node[sta].son=seek_num; seek_num++; seek[seek_num].point=sta; seek[seek_num].next=node[end].son; node[end].son=seek_num; return 0;};int fun(int fa,int ffa)// dp加递归{ int i,j,k,min; int price,power; int first,ii; for(i=node[fa].son;i!=0;i=seek[i].next)//索引fa的所有孩子再进行递归 { if(seek[i].point!=ffa)//防止死锁 fun(seek[i].point,fa);//递归 } first=1; for(i=node[fa].son;i!=0;i=seek[i].next)//索引fa的所有孩子i,分别在i以前的兄弟都已经进行dp的基础上进行dp { if(seek[i].point!=ffa) { if(first)//当是i第一个孩子时dp[fa][ii]的值为dp[i][ii]; { first=0; for(ii=0;ii<=money;ii++) dp[fa][ii]=dp[seek[i].point][ii]; } else { memset(temp,0,sizeof(temp)); for(j=money;j>=0;j--) //注意这里没有严格要求一定是从money……0,因为我用了一个temp { for(k=0;k<=j;k++)//进行dp[i][j]=max{(power<dp[i][j-price])?power:dp[i][j-price]} { min=(dp[seek[i].point][k]<dp[fa][j-k])?dp[seek[i].point][k]:dp[fa][j-k]; if(min>temp[j]) temp[j]=min; } } for(j=0;j<=money;j++) dp[fa][j]=temp[j]; } } } memset(temp,0,sizeof(temp));//这是一大败笔,但是考虑到这也是我的一个成长历程,纪念一下,就没去改了, //有兴趣的你可以试试去掉它!(提示:内外循环交换) for(i=0;i<=count[fa];i++)//此只讨论i的各种选择 { if(!i) price=power=0;//当fa点一个防御系统都不修建的情况! else price=node[fa].k[i][0],power=node[fa].k[i][1]; for(j=money;j>=0;j--)//进行dp[i][j]=max{dp[i][j],dp[i][j-price]+power} { if(j>=price) { if(temp[j]<power+dp[fa][j-price]) temp[j]=power+dp[fa][j-price]; } else break; } } for(j=0;j<=money;j++) dp[fa][j]=temp[j]; return 0;}int main(){ int T,i,j,n; int v,u,choice;// freopen("input.txt","r",stdin); scanf("%d",&T);//测试数据 while(T--) { scanf("%d",&n);//节点数 for(i=1;i<=n;i++)//初始化,为索引做准备 node[i].son=0; for(i=0;i<2010;i++)//初始化,为索引做准备 seek[i].next=0; seek_num=0;//初始化,为索引做准备 for(i=1;i<n;i++) { scanf("%d%d",&v,&u); add_son(v,u);//分别为v,u增加儿子 } scanf("%d",&money);//总的钱 for(i=1;i<=n;i++) { scanf("%d",&choice);//每个点有多少种选择 count[i]=choice; for(j=1;j<=choice;j++) scanf("%d%d",&node[i].k[j][0],&node[i].k[j][1]);//防御系统对应的价格和防御能力值 } memset(dp,0,sizeof(dp)); fun(1,-1);//调用递归进行树形dp printf("%d\n",dp[1][money]); } return 0;}
- hdu 4044 GeoDefense
- hdu 4044 GeoDefense
- HDU 4044 GeoDefense
- HDU 4044 GeoDefense
- hdu 4044 GeoDefense
- GeoDefense HDU
- hdu 4044 GeoDefense 树形dp+分组背包
- hdu 4044 GeoDefense(DP-树形DP)
- hdu 4044 GeoDefense 树形dp+分组背包
- HDU 4044 GeoDefense(动态规划)
- HDU 4044 GeoDefense 树形DP+分组背包
- hdu 4044 GeoDefense 树形DP+分组背包
- HDU 4044 GeoDefense(树形dp+分组背包)
- hdu 4044 GeoDefense (树形dp | 多叉树转二叉树)
- hdu 4044 GeoDefense (树形dp+01背包)
- HDU ACM 4044 GeoDefense ->树形DP+分组背包
- HDU 4044 GeoDefense 树形dp:树形背包★
- HDU 4044 GeoDefense(树形DP+分组背包)★
- 成都区域赛区Maze杭电4035(dp求期望)
- poj2653 - Pick-up sticks
- general error c101008a: Failed to save the updated manifest to the file ".\D
- 用Random(0,1)来实现Random(a,b)
- 修改Tomcat端口号
- hdu 4044 GeoDefense
- javascript中replace的使用
- 强大的JS,增加删除表格数据。
- 通过bbed修改表的数据内容
- hdoj 1232 畅通工程
- IaaS平台架构(一):价值
- 友善之臂Micro2440下的Embedded Linux中Java遇到的问题
- 摘抄
- poj 2396 budget