首页 > [JSOI2008]魔兽地图

[JSOI2008]魔兽地图

树上背包

题目传送门

首先,有没有哪位dalao 愿意告诉我为什么合成高级装备不需要附加金币,,

 

好吧,这个不重要

明确表示装备合成路线可以用一棵树来表示。一颗?傻乎乎的在下之前每次就只dp一棵树,不出意外的WA了,,在看几遍,好嘛,好像是个森林啊(泪奔)

最容易想到的dp[x][i][j]是第x件买了i个,花了j元的最高力量。但是,,这样好像就成为不可做题了(欢迎各路dalao打脸,反正不是我说的[手动滑稽](偷偷扔出FYJ挡枪)),那么换一种思路,还是dp[x][i][j],但表示的是第x件装备,用i件合成上级装备(即至少买了i件),花费j元的力量。如果i是基础装备,转移方程就直接出来了:d[x][i][j*cost[x]]=power[x]*(j-i)。

 如果是高级装备呢?

那就枚举它买多少件,以及它的子装备买多少件,直接暴力转移,n^2*times^2。看看时限,3s,完全不方

在下代码比较丑,求各位不要介意

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include<set>
#include
#include
#define ll int
#define re register
#define inf 0x3f3f3f3f
#define inl inline
#define sqr(x) (x*x)
//#define eps 1e-8
#define debug printf("debug
");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
using namespace std;
//const ll mod;
const ll MAXN=3e5+10;
inl ll read() {re ll x = 0; re int f = 1;char ch = getchar();while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x * f;
}
inl char readc() {char ch=getchar();while(('z''a')&&('Z''A')) ch=getchar();return ch;
}
inl void write(re ll x){if(x>=10)write(x/10);putchar(x%10+'0');
}
inl void writeln(re ll x){if(x<0) {x=-x;putchar('-');}write(x); puts("");
}
inl ll gcd(re ll x,re ll y){ while(y^=x^=y^=x%=y);return x;}
inl void FR() {freopen(".in","r",stdin);freopen(".out","w",stdout);
}
inl void FC() {fclose(stdin);fclose(stdout);
}
struct Node {ll u,v,w,nxt;
}e[20005<<1];
ll cnt,head[60],ssw[60],g[20005],cost[60],times[60];
bool fl[60],in[60],vis[60];
ll ans[20005];
inl void adde(ll u,ll v,ll w) {e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;
}
ll d[60][105][2005],n,m;
void dp(ll x) {if(vis[x]) return ;vis[x]=1;if(!fl[x]) { //基础装备 times[x]=min(times[x],m/cost[x]);for(re ll i=times[x];~i;i--) {for(re ll j=i;j<=times[x];j++) {d[x][i][j*cost[x]]=ssw[x]*(j-i);}}return ;}for(re ll h=head[x];h;h=e[h].nxt) {dp(e[h].v);cost[x]+=e[h].w*cost[e[h].v];times[x]=min(times[x],times[e[h].v]/e[h].w);}times[x]=min(times[x],m/cost[x]);for(re ll i=times[x];~i;i--) {for(re ll j=1;j<=m;j++) g[j]=-inf;g[0]=0;for(re ll h=head[x];h;h=e[h].nxt) {for(re ll k=m;~k;k--) {re ll sst=-inf;for(re ll l=0;l<=k;l++) {sst=max(sst,g[k-l]+d[e[h].v][i*e[h].w][l]);}g[k]=sst;//花k元能到的最高力量 
            }}for(re ll j=0;j<=i;j++) {for(re ll l=0;l<=m;l++) {d[x][j][l]=max(d[x][j][l],g[l]+ssw[x]*(i-j));}}}
}
int main(){
//    FR();n=read(),m=read();memset(times,inf,sizeof(times));memset(d,-inf,sizeof(d));for(re ll i=1;i<=n;i++) {ssw[i]=read();char sj[3];scanf("%s",sj);if(sj[0]=='A') {fl[i]=1;re ll c=read();for(re ll j=1;j<=c;j++) {re ll sx=read(),xs=read();if(!in[sx]) in[sx]=1;adde(i,sx,xs);}}else if(sj[0]=='B') {fl[i]=0;cost[i]=read();times[i]=read();}else puts("RE");}for(re ll i=1;i<=n;i++) {if(!in[i]) { //被坑无数次 
            dp(i);for(re ll j=m;~j;j--) {for(re ll k=0;k<=j;k++) {ans[j]=max(ans[j],ans[j-k]+d[i][0][k]);}}}}writeln(ans[m]);
//    FC();return 0;
}

 

转载于:https://www.cnblogs.com/20020723YJX/p/9348020.html

更多相关:

  • L1-056 猜数字 (20 分) 一群人坐在一起,每人猜一个 100 以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。 输入格式: 输入在第一行给出一个正整数N(≤104)。随后 N 行,每行给出一个玩家的名字(由不超过8个英文字母组成的字符串)和其猜的正整数(≤ 100)。 输出格式: 在一行中...

  • 达哥送分给我我都不要,感觉自己挺牛批。 $type=0:$ 跟visit那题类似,枚举横向移动的步数直接推公式: $ans=sum C_n^i imes C_i^{frac{i}{2}} imes C_{n-i}^{frac{n-i}{2}},i\% 2=0$ $type=1:$ 因为不能触碰负半轴,所以可以把右移看成...

  • 题目链接 题意:给你三个数n,m,k;让你构造出一个nm的矩阵,矩阵元素只有两个值(1,-1),且满足每行每列的乘积为k,问你多少个矩阵。 解法:首先,如果n,m奇偶不同,且k=-1时,必然无解: 设n为奇数,m为偶数,且首先要满足每行乘积为-1,那么每行必然有奇数个-1,那么必然会存在有偶数个-1.。满足每列乘积为-1,那么每列必...

  • Description 有 n 种数字,第 i 种数字是 ai、有 bi 个,权值是 ci。 若两个数字 ai、aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值。 一个数字只能参与一次配对,可以不参与配对。 在获得的价值总和不小于 0 的前提下,求最多进行多少次配对...

  • 快速幂       1 #include 2 #include 3 #include 4 #define LL long long 5 using namespace std; 6 7 LL Pow(LL a, LL b) 8 { 9 LL an...

  •  给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 示例 1: 输入: 123 输出: 321  示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: 21 注意:假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231,  231 − 1]。请根据这个...

  • $dp$。 这道题最关键的是这句话: 跳出思维局限大胆设状态,设$f_{x, i, j}$表示从$x$到根要经过$i$条公路,$j$条铁路的代价,那么对于一个叶子结点,有$f_{x, i, j} = c_x * (a_x + i) * (b_x + j)$,对于内部结点,有转移:   $f_{x, i, j} = min(f_{lso...

  • 合作者:201631062327,201631062128码云地址:https://gitee.com/LIUJIA6/WordCount3 一:项目说明 本次项目是在上次作业WorldCount的基础上,利用结对编程的思想,完成对WorldCount项目的功能扩展 -s 递归处理目录下符合条件的文件。(实现)-a 返回更复杂的数据(...

  • Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。 例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生...

  •   【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5972   【题目大意】   给出一个字符串,找出其中所有的符合特定模式的子串位置,符合特定模式是指,该子串的长度为n,并且第i个字符需要在给定的字符集合Si中    【题解】   利用ShiftAnd匹配算法。   bt[i]表示...

  • 首先我们可以发现如果错过了一个加油站,而继续往前走的时候没有油了,可以再假装之前经过加油站的时候加过油 于是我们维护一个大根堆,表示错过的加油站是哪些,每当没有油的时候从堆顶取出最大值加上去即可   1 /**************************************************************...