fjnu2019第二次友谊赛 F题
题目大意:
一开始手上有 z 个钱币,有 n 天抉择,m 种投资方案,在每天中可以选择任意种投资方案、任意次地花费 x 个钱币(手上的钱币数不能为负),使得在 n 天结束后,获得 y 个钱币。
其次,在每天结束后,会根据自己手上所具有的节点数来获得一些钱币补偿,设当天结束后所拥有 x 个钱币,那么将获得 f(x) 个钱币,若 x > k ,则默认为 0 。保证 f[0]~f[k] 单调不增。
这题的原题:博客连接 ,只是一开始手上的钱数不同而已。
分析:
1、将全过程分为 n 天,在 dp 枚举每天的状态时,先处理当天一开始所拥有的钱币数(即上一天结束后手上的钱数),再进行当天的投资。所以我们将当天投资结束后的补偿状态在下一天的早上进行转移,而不是在当天结束后进行状态转移。
2、故设 dp[i][j] 表示在第 i 天投资完之后(当天还未获得补偿),在手上拥有 j 个钱币时,在 n 天结束后所获得的返还的最大钱币总数。
3、那么对于每一天的一开始钱币数是由上一天补偿之后而转移过来的,由于补偿只会在有剩下 0 ~ k 个钱币时才会发生 (即 手上钱币数为 0 ~ k 时才可能获得补偿),故在每天开始前需要遍历上一天手中剩下的钱币数,获得一定的补偿之后,成为今天一开始的钱币数。
4、获得当天的钱币数后,开始进行今天的投资状态转移。由于投资的数量为任意次,故为完全背包的转移。
5、若对于当天投资结束后手上有 j 元时的状态( 即 dp[i][j] ),它必从当天投资一开始的手上钱币为 ( j + 投资成本 )时,花费投资成本后转移而来。故若设投资成本为 w ,最后一天返还 v ,则有 dp[i][j] = dp[i][j + w] + v ,完全背包取最大值即可。
6、由于一开始有钱币数,而按上面所述,第一天一开始不能从上一天剩余钱币数上转移,故第一天需要单独拿出来先处理。
7、初始化问题:按理这题 dp 需要求最大值,全部初始化为 0 才对,但是需要保证本题的实际意义——需要从第一天手上 z 个钱币时转移,故需要初始化全部为负无穷,然后将dp[1][z] 赋值为 0 ,表明 dp 转移时,必须从第一天手上有 z 个钱币时转移而来。
8、由于我们将第一天枚举单独拿出来了,即意味着求的所有状态都必须在第一天买东西才会被转移到第二天(即第一天啥都不买时,这个状态不会被传递下去),然后再进行下面的每天转移。故我们求答案时,还需要判断是否 n 天啥都不投资的钱币会更多(意思是如果第一天啥都不买,最大值不可能轮到第二天才开始买)。
注意点:
1、若按上述这样直接做的话,复杂度接近 n³ * k (k 为常数),此题数据将会有 3000MS (当然出题人良心放宽时限)。
2、若要降低时间复杂度,需要知道完全背包去掉枚举方案个数的原理。这个原理其实是当前 dp[i][j] 从本层之前已更新过的状态转移过来(详细则自己百度或群里问)。
3、此题与普通完全背包降维不同的是,分析 dp 转移方程,发现他是从后往前转移的 (即 dp[i][j] 中的 j 从 j + w 上转移而来),优化时,需要反向枚举背包容量。
无优化代码:
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int z,N,M,K;
int dp[][];
int f[];
struct Goods{
int a,b;
}A[];
int main()
{
scanf("%d%d%d%d",&z,&N,&M,&K);
for(int i=;i<=K;i++) scanf("%d",&f[i]);
for(int i=;i<=M;i++) scanf("%d%d",&A[i].a,&A[i].b);
memset(dp,0x80,sizeof(dp));
dp[][z]=;
for(int w=;w<=M;w++){
for(int j=A[w].a;j<=;j++){
for(int k=;k<=j/A[w].a;k++){
dp[][j-k*A[w].a]=max(dp[][j-k*A[w].a],dp[][j]+k*A[w].b);
}
}
}
for(int i=;i<=N;i++){
for(int j=;j<=K;j++) dp[i][j+f[j]]=max(dp[i][j+f[j]],dp[i-][j]);
for(int w=;w<=M;w++){
for(int j=A[w].a;j<=;j++){
for(int k=;k<=j/A[w].a;k++){
dp[i][j-k*A[w].a]=max(dp[i][j-k*A[w].a],dp[i][j]+k*A[w].b);
}
}
}
}
int ans=z;
for(int i=;i<=;i++) ans=max(ans,dp[N][i]+i+f[i]);
printf("%d\n",ans);
}
优化代码:
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int z,N,M,K;
int dp[][];
int f[];
struct Goods{
int a,b;
}A[];
int main()
{
scanf("%d%d%d%d",&z,&N,&M,&K);
for(int i=;i<=K;i++) scanf("%d",&f[i]);
for(int i=;i<=M;i++) scanf("%d%d",&A[i].a,&A[i].b);
memset(dp,0x80,sizeof(dp));
dp[][z]=;
for(int w=;w<=M;w++){
for(int j=;j>=A[w].a;j--){
dp[][j-A[w].a]=max(dp[][j-A[w].a],dp[][j]+A[w].b);
}
}
for(int i=;i<=N;i++){
for(int j=;j<=K;j++) dp[i][j+f[j]]=max(dp[i][j+f[j]],dp[i-][j]);
for(int w=;w<=M;w++){
for(int j=;j>=A[w].a;j--){
dp[i][j-A[w].a]=max(dp[i][j-A[w].a],dp[i][j]+A[w].b);
}
}
}
int ans=z;
for(int i=;i<=;i++) ans=max(ans,dp[N][i]+i+f[i]);
printf("%d\n",ans);
}
fjnu2019第二次友谊赛 F题的更多相关文章
- fjnu2019第二次友谊赛 B题
### 题目链接 ### 题目大意: 给你一个 n * m 的地图以及小蛇蛇头的初始位置,告诉你它会往 上.下.左.右 四个方向走.若在走的过程中(包括结束时)会使得小蛇越界,则输出 "Ga ...
- 2013年山东省赛F题 Mountain Subsequences
2013年山东省赛F题 Mountain Subsequences先说n^2做法,从第1个,(假设当前是第i个)到第i-1个位置上哪些比第i位的小,那也就意味着a[i]可以接在它后面,f1[i]表示从 ...
- 2017Summmer_上海金马五校 F题,G题,I题,K题,J题
以下题目均自己搜 F题 A序列 一开始真的没懂题目什么意思,还以为是要连续的子串,结果发现时序列,简直智障,知道题意之后,好久没搞LIS,有点忘了,复习一波以后,直接双向LIS,处理处两个数组L和R ...
- ACM-ICPC 2019南昌网络赛F题 Megumi With String
ACM-ICPC 南昌网络赛F题 Megumi With String 题目描述 给一个长度为\(l\)的字符串\(S\),和关于\(x\)的\(k\)次多项式\(G[x]\).当一个字符串\(str ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- AtCoder Beginner Contest 215 F题题解
F - Dist Max 2 什么时候我才能突破\(F\)题的大关... 算了,不说了,看题. 简化题意:给定\(n\)个点的坐标,定义没两个点的距离为\(min(|x_i-x_j|,|y_i-y_j ...
- 2019年牛客多校第二场 F题Partition problem 爆搜
题目链接 传送门 题意 总共有\(2n\)个人,任意两个人之间会有一个竞争值\(w_{ij}\),现在要你将其平分成两堆,使得\(\sum\limits_{i=1,i\in\mathbb{A}}^{n ...
- (中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。
"Couple Trees" are two trees, a husband tree and a wife tree. They are named because they ...
- AtCoder Beginner Contest 213 F题 题解
F - Common Prefixes 该题也是囤了好久的题目了,看题目公共前缀,再扫一眼题目,嗯求每个后缀与其他后缀的公共前缀的和,那不就是后缀数组吗?对于这类问题后缀数组可是相当在行的. 我们用后 ...
随机推荐
- 11条MySQL规范,你知道的有几个?
一.数据库命令规范 · 所有数据库对象名称必须使用小写字母并用下划线分割 · 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) · 数据库对象的命名 ...
- centos7 启动停止命令
apache启动systemctl start httpd停止systemctl stop httpd重启systemctl restart httpd mysql启动systemctl start ...
- Vue ---- 组价 组件化 子传父 父传子
目录 补充js的for循环: 组件 1.组件的分类: 2.组件的特点 3.创建局部组件 4.全局组件 二.组件化 一.组件传参父传子 二.组件传参:子传父 补充js的for循环: // for in遍 ...
- 《Java知识应用》Linux系统下word转PDF
仅供学习,如需商用请联系开发商:https://apireference.aspose.com/java/words Jar包下载路径: 链接: https://pan.baidu.com/s/1s7 ...
- GTC 2019参会整理
NVIDIA GTC 2019在苏州金湖国际会议中心举行,由于同事有其他会议冲突,所以我代替他来参加了此次会议.作为刚接触GPU和机器学习不久的新人来说,感觉进入了一个新世界,深刻体验到技术的革新迭代 ...
- 关于爬取babycenter.com A-Z为顺序的所有英文名及其详细属性
这一次爬取的内容已经在标题里提到了,下面是详细要求及其图示: 1.首先以A-Z的顺序获取所有英文名,最后爬取该英文名的详细信息. 2.CSV的header以3中的单词为准,请别拼错.如果没有对应的数 ...
- 【CV现状-3.2】纹理与材质
#磨染的初心--计算机视觉的现状 [这一系列文章是关于计算机视觉的反思,希望能引起一些人的共鸣.可以随意传播,随意喷.所涉及的内容过多,将按如下内容划分章节.已经完成的会逐渐加上链接.] 缘起 三维感 ...
- leetcode之缺失的第一个正数
给定一个未排序的整数数组,找出其中没有出现的最小的正整数. 示例 1: 输入: [1,2,0]输出: 3示例 2: 输入: [3,4,-1,1]输出: 2示例 3: 输入: [7,8,9,11,12] ...
- CSS样式 解决文字过长显示省略号问题
一.CSS样式 解决文字过长显示省略号问题 1.一般样式 一般 css 样式,当宽度不够时,可能会出现换行的效果.这样的效果在某些时候肯定是不行的,可以修改 css 样式来解决这个问题. <!D ...
- Asp.Net MVC Webapi Eventsource 实现时效消息
ApiController 后端API public System.Net.Http.HttpResponseMessage GetUnknownNotices() { var user = Form ...