2018SCin tsyzDay2 模拟赛-动态规划(简单的)
内心OS:简单?????还是我太弱了。
期望得分:100+100+0+0+0+0+随机暴力的点==200
实际得分:0+100+10+0+10+0==120
您知道我第一题为什么错了嘛??文件在混乱中被我注释掉了
mmp.
T1


三月份考过这道题--记忆化搜索。
还写过题解,提醒这里样例给错了orz。
放上链接QAQ http://www.cnblogs.com/nopartyfoucaodong/p/8589116.html
和滑雪一样,听说这是一道棋盘dp? 不解。
§ 注意边界的处理,防止越界。
§ 因为是跳的次数,所以最后要减一。
code
#include<cstdio>
#include<algorithm> using namespace std; int n,m,ans;
int dx[]={-,,,};
int dy[]={,,-,};
int w[][];
int f[][];
int memory_search(int x,int y)
{
if(f[x][y]) return f[x][y];
int tmp=;
for(int i=;i<;i++)
{
int tx=x+dx[i];int ty=y+dy[i];
if(w[tx][ty]>w[x][y]&&tx>=&&tx<=n&&ty>=&&ty<=m) tmp=max(memory_search(tx,ty)+,tmp);
// else continue;
}
f[x][y]=tmp;
return f[x][y];
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&w[i][j]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
ans=max(ans,memory_search(i,j));
printf("%d",ans+);
fclose(stdin);
fclose(stdout);
return ;
}
T2
二进制优化多重背包裸题,二月考过。
T3
noip能量项链原题。
https://www.luogu.org/problemnew/show/P1063
Chemist没有做过能在考场上1A,%一%!!!
加强了对区间dp的理解!
一般地,我们在求解区间型动态规划时,会把一个个区间作为各个阶段。
一般地,需要用到三层循环进行枚举,外层为区间长度,其次为端点,最内层为断点。
另外,本题还需要断环成链,开long long。
code
#include<cstdio>
#include<algorithm> using namespace std;
typedef long long ll; int n;
ll a[];
ll ans,f[][]; int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
a[i+n]=a[i];
}
for(int len=;len<=n+;len++)
for(int i=;i+len-<=*n;i++)
{
int j=i+len-;
for(int k=i+;k<=j-;k++)
f[i][j]=max(f[i][j],f[i][k]+f[k][j]+a[i]*a[k]*a[j]),ans=max(ans,f[i][j]);
}
printf("%lld",ans);
//fclose(stdin);
//fclose
return ;
}
T4


是一道典型的动态规划。
状态设计: f[i][j]表示在前i个数中取j个的和的最大值。
《初始化1》我们从数据中可以发现,序列是有负数的。所以我们初始要把f数组和ans设为负无穷。
但是我们鬼畜地发现,用for循环不能进行初始化,必须得用memset(QAQ为什么呀)
memset(f,,sizeof(f))
这句可以赋为负无穷,0x3f可以赋为正无穷。
《初始化2》
对f数组进行初始化:在j为1时,不受选的个数限制。
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
f[i][]=max(f[i-][],a[i]);
转移方程:
f[i][j]=max( f[i-k][j-1]+a[i] 【取,受i>=k的限制】, f[i-1][j] 【不取】 )
code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm> using namespace std; int n,m,k,ans=-0x7fffffff;
int a[],f[][]; int main()
{
freopen("4.in","r",stdin);
freopen("4.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
//为什么for循环不行qaq
//for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) f[i][j]=-0x7fffffff;
memset(f,,sizeof(f));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
f[i][]=max(f[i-][],a[i]);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
f[i][j]=max(f[i-][j],f[i][j]);
if(i>=k) f[i][j]=max(f[i][j],f[i-k][j-]+a[i]);
}
printf("%d",f[n][m]);
fclose(stdin);
fclose(stdout);
return ;
}
T5





我们看一看官方的题解好了XD
感觉分析的很透彻呀
看完题目后,对题目分析可知,此题的最优解法就是动态规划。
当然,因为有两个坩锅,所以明显是一道双进程动态规划题目。因此,先用动态规划求解一个坩锅能达到的最大药效,把已用的药材去掉,再次动态规划的方法是不可行的!
1.分析最优子结构:
数据备注:
t1[i]表示第i种药材的起始时间
t2[i]表示第i种药材的结束时间
w[i]表示第i种药材的药效
time表示总时间 n表示药材总数
(为了让大家更好理解 先讲一种未优化的算法)
设动态规划数组 dp[i][j][k] 表示前i种药材放入两个坩锅,第一个坩锅达到时间j,第二个坩锅达到k时所能达到的最大药效。题目的解就是dp[n][time][time];
因为要知道在time时刻两个坩锅的效益和,则需要用到它的子结构的最优值。
分析子结构的最优值的取得条件:
对于第i种药材,放入两个坩锅,有三种处理方法:
1. 把它放入第一个坩锅;
2. 把它放入第二个坩锅;
3. 不放入任何坩锅
对1:
dp[i][j][k]=dp[i-1][t1[i]-1][k]+w[i]; 条件:仅当j=t2[i];
对2:
dp[i][j][k]=dp[i-1][j][t1[i]-1]+w[i]; 条件:仅当k=t2[i];
对3:
dp[i][j][k]=max{ dp[i-1][j][k], 无条件
dp[i][j-1][k], 条件 j>0
dp[i][j][k-1], 条件 k>0
因此 子结构dp[i][j][k]的取值就是对1,2,3种状态的最大值
即:
dp[i][j][k]=max{
dp[i-1][t1[i]-1][k]+w[i]; 条件:仅当j=t2[i]; // 个人注释:减一的意思是在开始的前一秒
dp[i-1][j][t1[i]-1]+w[i]; 条件:仅当k=t2[i];
dp[i-1][j][k], 无条件
dp[i][j-1][k], 条件 j>0
dp[i][j][k-1], 条件 k>0
}
2.解决后效性:
为了解决后效性,在这里,当且仅当j=t1[i]或k=t1[i]时,药材才会被放入坩锅内,且保证了同一种药品不会在以后被多次放入或者是同时放入二个坩锅,当然,仅仅是这样还是不能保证能求出最优解,因为在计算过程中,结构会被刷新,因此对于结束时间较晚的药材,若在结束时间较前的药材先被计算,则较前的药材就以为价值小而不会被记录,因此就应该在动态规划之前将数据按结束时间t2[i]升序排序。因此,我们完美的消除了后效性。
3.优化问题:
1.时间复杂度的优化:
根据对称性,两个坩锅不计先后,且一摸一样,因此dp[i][j][k]等价于dp[i][k][j],因此,在循环的时候可以令j<=k;然后加几个判断即可。具体方法不再赘述,请自行解决。
2.空间复杂度的优化:
在求解的过程中 即:dp[i][j][k]的值 只与 dp[i-1][…][…]的值有关,因此可以将数组降为2维 即:dp[j][k],具体方法不再赘述。可以看标程,标程有两个,一个是优化过的,一个是未经过优化的。
因此,对于这道题目,
近似最优时间复杂度为O(n^3)
近似最优空间复杂度为O(n^2)
code
#include<cstdio>
#include<algorithm> using namespace std; int T,n;
int f[][];
struct node{
int t1,t2,w;
}a[]; bool cmp(node x,node y)
{
return x.t2<y.t2;
} int main()
{
freopen("medic.in","r",stdin);
freopen("medic.out","w",stdout);
scanf("%d%d",&T,&n);
for(int i=;i<=n;i++)
scanf("%d%d%d",&a[i].t1,&a[i].t2,&a[i].w);
sort(a+,a+n+,cmp);
for(int i=;i<=n;i++)
for(int j=T;j>=;j--)
for(int k=T;k>=;k--)
{
if(j>=a[i].t2) f[j][k]=max(f[j][k],f[a[i].t1-][k]+a[i].w);
if(k>=a[i].t2) f[j][k]=max(f[j][k],f[j][a[i].t1-]+a[i].w);
}
printf("%d",f[T][T]);
fclose(stdin);
fclose(stdout);
return ;
}
小结,这几天做了好多动规(水题),遇到多维的时候,判断条件也会几层(循环层数),为了维持下去,可加入特判(如本题的if)
2018SCin tsyzDay2 模拟赛-动态规划(简单的)的更多相关文章
- 2018SCin tsyzDay1 模拟赛-模拟
预计得分:70+0+0+100+100+100+100=470 实际得分:70+0+0+30+100+0+40=240 第一天就被模拟虐爆qwq T1 https://www.luogu.org/pr ...
- noip模拟赛 动态规划
题目描述LYK在学习dp,有一天它看到了一道关于dp的题目.这个题目是这个样子的:一开始有n个数,一段区间的价值为这段区间相同的数的对数.我们想把这n个数切成恰好k段区间.之后这n个数的价值为这k段区 ...
- 2016-06-19 NOIP模拟赛
2016-06-19 NOIP模拟赛 by coolyangzc 共3道题目,时间3小时 题目名 高级打字机 不等数列 经营与开发 源文件 type.cpp/c/pas num.cpp/c ...
- NOIP前模拟赛总结
NOIP前模拟赛总结 from 2018.10.7 to ??? Date Name Score(Rank) Problems 2018.10.7 McfXH AK Contest 42(?) 期望得 ...
- NOIP2017提高组模拟赛 7(总结)
NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...
- 2020.3.23 模拟赛游记 & 题解
这次的模拟赛,实在是水. 数据水,\(\texttt{std}\) 水,出题人水,做题人也水.??? 游记就说一句: 水. T1 metro 弱智题. 人均 \(100pts\). #pragma G ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
- NOIP第7场模拟赛题解
NOIP模拟赛第7场题解: 题解见:http://www.cqoi.net:2012/JudgeOnline/problemset.php?page=13 题号为2221-2224. 1.car 边界 ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
随机推荐
- JDBC调用存储过程,进参出参
今天做了一个数据表拷贝的功能,用到了存储过程,就写了一个java中用jdbc调用存储过程的代码,成功的实现了功能,晚上跑回家记录下 Connection conn = ConnectionUtil.g ...
- java验证身份证号码是否有效源代码
原文:http://www.open-open.com/code/view/1420373343171 1.描述 用java语言判断身份证号码是否有效,地区码.出身年月.校验码等验证算法 2.源代码 ...
- linux安装mail服务使用外部MTA发送邮件
阉割版的linux没有mail命令,也没有/etc/mail.rc文件 需要安装mail服务 yum install mailx.x86_64 几个概念:MUA.MTA.MDA 邮件用户代理(MUA, ...
- FPGA第一篇:SRAM工作原理
一.SRAM概述 SRAM主要用于二级快速缓存(Level2 C ache). 它利用晶体管来存储数据.与DRAM相比,SRAM的速度快,但在同样面积中SRAM的容量要比其它类型的内存小. 大部分FP ...
- 关于axis2.1.6与websphere7的包冲突问题的解决方式
1,复制axis2.1.6内的module目录内的全部文件到lib 并改动扩展名为.jar 2,删除module目录(可选,不删除也能够) 3,部署到was 4,设置was相应应用程序的类载入方案为父 ...
- Spring3+ibatis (SQL Server)+pager-taglib.tld查询分页的实现
pager-taglib分页開始~ 查了好多关于分页的技术,终于选定下面方法实现~ 1.首先下载jar包:pager-taglib.jar,pager-taglib.jar放在WEB-INF/lib文 ...
- 内存转储文件 Memory.dmp
https://baike.sogou.com/v63435711.htm?fromTitle=内存转存文件 内存转储是用于系统崩溃时,将内存中的数据转储保存在转储文件中,供给有关人员进行排错分析用途 ...
- 移动端和PC端有什么区别
1.PC考虑的是浏览器的兼容性,而移动端开发考虑的更多的是手机兼容性,因为目前不管是android手机还是ios手机,一般浏览器使用的都是webkit内核,所以说做移动端开发,更多考虑的应该是手机分辨 ...
- Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve com.android.support.constraint:constraint-layout:1.1.0. Could not resolve com.android.support.constraint:constraint-l
File->Settings->Build, Execution, Deployment->Gradle->取消选中 Offline work 按钮
- forword 与 redirect
直接转发方式(Forward) 客户端和浏览器只发出一次请求,Servlet.HTML.JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每个信息资源是共享的 ...