bzoj1017(JSOI2008)魔兽地图
2024-10-21 19:08:07
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1017
钱数很少,所以它也能压进状态里。
还有向上贡献几个物品。所以状态就是第 i 号物品,向上贡献 j 个,总共花 k 元的当前就能得到的力量。
然后可以树形dp。
不同的是平常的树形dp,该点的值就顺便充当前 r 个子树的值;遍历完子树就完成自己的值。
但这里的状态里有一个“向上贡献 j 个”,不太好弄。所以另开一个 g ,只关注花了多少钱和带来多少力量。
为了能用这个g转移到dp,不出现花了某些钱其实买不够向上贡献的 j 个当前物品的情况,应该把“总共买 l 个当前物品”放在最外面枚举。
并且是倒序,为了沿用上一轮的g值。
**不知为何,自己的代码比别人慢了好多!!我觉得没什么不同呀……以后再来看看吧。
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=,M=;const ll INF=0x7fffffff;
int n,m,head[N],xnt,du[N];
ll a[N],L[N],c[N],dp[N][N<<][M],g[N][M],h[N][M],ans;//dp[][N<<1][]不能dp[][N][]
struct Edge{
int next,to;ll w;
Edge(int n=,int t=,ll w=):next(n),to(t),w(w) {}
}edge[N];
void dfs(int cr)
{
if(!head[cr])
{
L[cr]=min(L[cr],m/c[cr]);
for(int i=;i<=L[cr];i++)
for(int j=;j<=i;j++)
dp[cr][j][i*c[cr]]=(i-j)*a[cr];
return;
}
L[cr]=INF;
for(int i=head[cr],v;i;i=edge[i].next)
{
dfs(v=edge[i].to);L[cr]=min(L[cr],L[v]/edge[i].w);
c[cr]+=c[v]*edge[i].w; //只是用来限制L[cr]
}
L[cr]=min(L[cr],m/c[cr]);
memset(g,-,sizeof g);//g只和子树阶段、钱有关,因为dp涉及"向上贡献几个",所以不方便同时表示前几个子树的力量值
g[][]=;
for(int l=L[cr];l>=;l--)//g不重赋值,所代表的状态应该足以合成当前的l个当前装备;所以需倒序
{
int tot=;
for(int i=head[cr];i;i=edge[i].next)
{
tot++;
for(int k=;k<=m;k++)//用了k钱
for(int j=;j<=k;j++)//j钱给v
g[tot][k]=max(g[tot][k],g[tot-][k-j]+dp[edge[i].to][l*edge[i].w][j]);//k-j钱给之前的子树
}
for(int j=;j<=l;j++)
for(int k=;k<=m;k++)
dp[cr][j][k]=max(dp[cr][j][k],g[tot][k]+a[cr]*(l-j));//子树们的节余+自己的节余
}
}
int main()
{
scanf("%d%d",&n,&m);char ch;int u,x;ll z;
memset(L,,sizeof L);
memset(dp,-,sizeof dp);//////
for(int i=;i<=n;i++)
{
scanf("%lld %c",&a[i],&ch);
if(ch=='B')
{
scanf("%lld%lld",&c[i],&L[i]);
}
else
{
scanf("%d",&u);
for(int j=;j<=u;j++)
{
scanf("%d%lld",&x,&z);
edge[++xnt]=Edge(head[i],x,z);head[i]=xnt;du[x]++;
}
}
}
int tot=;
for(int i=;i<=n;i++)
if(!du[i])
{
dfs(i);tot++;
for(int k=;k<=m;k++)//总共
for(int j=;j<=m;j++)//给之前的树
h[tot][k]=max(h[tot][k],h[tot-][j]+dp[i][][k-j]);
}
for(int i=;i<=m;i++)ans=max(ans,h[tot][i]);
printf("%lld",ans);
return ;
}
最新文章
- 使用Python中PIL图形库进行截屏
- 动态修改attr里的多个属性
- C#中String类的几个方法(IndexOf、LastIndexOf、Substring)
- OpenStack Swift client开发
- javascript学习笔记(2)
- 网站添加icon
- C#C/S框架演示 (MES系统)
- TCP首部
- java中随机二维数组中寻找最大值并输出坐标
- httpd.yml实例
- es的scoll滚动查询技术
- java集合与包装类
- rowspan和colspan的区别粗解
- java数据结构之hashMap
- 【bzoj4540】 Hnoi2016—序列
- # 2017-2018-1 20155232《信息安全技术》实验二——Windows口令破解
- Siki_Unity_2-3_UGUI_Unity4.6 UI Beta版本入门学习(未学)
- LOJ 2172 「FJOI2016」所有公共子序列问题——序列自动机
- ffmpeg 学习
- 搜索引擎--范例:谈谈django--mysql数据库的一些常用命令
热门文章
- 第六天 vim编辑的使用和Xmanager远程工具的使用
- Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache
- iOS开发图片加载的内存问题及优化方案
- vue请求本地json数据
- Frequently-Used Network Time Server(Base On NTP:Network Time Protocol)
- 团队项目:";Jarvis For Chat";
- SQL Plus常用命令
- C++11_ Lambda
- vue.js 源代码学习笔记 ----- 工具方法 error
- GNU Autotools的使用方法