【经典】Noip动态规划
一、线性动态规划
最长严格上升子序列
#include<iostream> #include<cstdio> using namespace std; int n,ans; int a[5004],dp[5004]; int main() {scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=n;i++){for(int j=1;j<i;j++){if(a[j]<a[i])dp[i]=max(dp[i],dp[j]+1);ans=max(ans,dp[i]);}}printf("%d\n",ans+1);return 0; }
最长严格上升子序列
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=0x3f3f3f3f; int n,a[1000009],dp[1000009]; int main() {scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);memset(dp,0x3f,sizeof(dp));for(int i=1;i<=n;i++){int p=upper_bound(dp+1,dp+n+1,a[i])-dp;if(a[i]!=dp[p-1])//严格上升序列 dp[p]=a[i];}for(int i=1;i<=n+1;i++){if(dp[i]==maxn){printf("%d\n",i-1);return 0;}}return 0; }
nlogn
变形:打鼹鼠
#include<iostream> #include<cstdlib> #include<cstdio> using namespace std; int maxt,n,m,ans,x[10001],y[10001],t[10001],f[10001]; int main() {int i,j;scanf("%d%d",&n,&m);for (i=1;i<=m;++i)scanf("%d%d%d",&t[i],&x[i],&y[i]);for (i=1;i<=m;++i){f[i]=1;//f表示到第i只鼹鼠出现时最多可以打到多少只 for (j=i-1;j>=1;--j)if (t[i]-t[j]>=abs(x[i]-x[j])+abs(y[i]-y[j]))//如果时间足够,能从j点移动到当前点 f[i]=max(f[i],f[j]+1);ans=max(ans,f[i]);}printf("%d",ans); }
Luogu打鼹鼠
二、背包
1)01背包
每个物品只有一个且只有选与不选两种可能
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int f[1002],w[1001],v[1001]; int n,m,t; int main() {scanf("%d",&t);while(t--){memset(f,0,sizeof(f));scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&v[i]);for(int i=1;i<=n;i++)scanf("%d",&w[i]);for(int i=1;i<=n;i++)for(int j=m;j>=w[i];j--)f[j]=max(f[j],f[j-w[i]]+v[i]);printf("%d\n",f[m]);} return 0; }
01背包
2)完全背包
每件物品数量无限
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int w1,w2,wi,t,k,f[10002],v[510],w[510]; int main() {scanf("%d",&t);while(t--){memset(f,0x3f,sizeof(f));f[0]=0; //**scanf("%d%d",&w1,&w2);wi=w2-w1;scanf("%d",&k);for(int i=1;i<=k;i++)scanf("%d%d",&v[i],&w[i]);for(int i=1;i<=k;i++)for(int j=w[i];j<=wi;j++)f[j]=min(f[j],f[j-w[i]]+v[i]);if(f[wi]==0x3f3f3f3f)printf("This is impossible.\n");elseprintf("The minimum amount of money in the piggy-bank is %d.\n",f[wi]);}return 0; }
完全背包
3)多重背包
每个物品数量一定
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int t,mon,k,w[102],pri[102],f[102],cnt[102]; int main() {scanf("%d",&t);while(t--){memset(f,0,sizeof(f));scanf("%d%d",&mon,&k);for(int i=1;i<=k;i++)scanf("%d%d%d",&pri[i],&w[i],&cnt[i]);for(int i=1;i<=k;i++){for(int j=mon;j>=pri[i];j--){for(int h=0;h<=cnt[i];h++){if(j-h*pri[i]<0)break;f[j]=max(f[j],f[j-h*pri[i]]+h*w[i]);}}}printf("%d\n",f[mon]);}return 0; }
多重背包
4)混合背包
-1为无限个
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std; int w[100000],v[100000],c[10000],dp[20000000]; int main() {int vv,n;scanf("%d%d",&n,&vv);for(int i=1;i<=n;i++)scanf("%d%d%d",&w[i],&v[i],&c[i]);for(int i=1;i<=n;i++){if(c[i]==-1){for(int j=w[i];j<=vv;j++){dp[j]=max(dp[j],dp[j-w[i]]+v[i]);}}else{int x=c[i];for(int j=1;j<=x;j<<=1){for(int k=vv;k>=w[i]*j;k--){dp[k]=max(dp[k],dp[k-w[i]*j]+v[i]*j);} x-=j;}if(x!=0){for(int j=vv;j>=x*w[i];j--){dp[j]=max(dp[j],dp[j-x*w[i]]+v[i]*x);}}}}printf("%d",dp[vv]);return 0; }
混合背包
5)二维费用背包
#include<bits/stdc++.h> using namespace std; int f[1010][1010]; int main(){int n,m,x;cin>>n>>m>>x;for(int i=1;i<=n;i++){int a,b,c;cin>>a>>b>>c;for(int j=m;j>=b;j--) //以下3行是算法的核心for(int k=x;k>=c;k--)f[j][k]=max(f[j][k],f[j-b][k-c]+a);}cout<<f[m][x];return 0; }
二维费用
6)有依赖性背包问题
#include<iostream> #include<cstdio> using namespace std; struct e {int v,p,q,w,f[66]; }g[66]; int n,m,f[35000]; int main() {scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d%d",&g[i].v,&g[i].p,&g[i].q);g[i].w=g[i].v*g[i].p;if(g[i].q!=0)g[g[i].q].f[++g[g[i].q].f[0]]=i;}for(int i=1;i<=m;i++){if(g[i].q==0){int f1=g[i].f[1],f2=g[i].f[2];for(int j=n;j>=g[i].v;j--){if(f1&&j-g[f1].v-g[i].v>=0)f[j]=max(f[j],f[j-g[i].v-g[f1].v]+g[i].w+g[f1].w);if(f2&&j-g[f2].v-g[i].v>=0)f[j]=max(f[j],f[j-g[i].v-g[f2].v]+g[i].w+g[f2].w);if(f1&&f2&&j-g[i].v-g[f1].v-g[f2].v>=0)f[j]=max(f[j],f[j-g[i].v-g[f1].v-g[f2].v]+g[i].w+g[f1].w+g[f2].w);f[j]=max(f[j],f[j-g[i].v]+g[i].w);}}}printf("%d\n",f[n]);return 0; }
依赖性背包
7)01背包求方案数
#include<iostream> #include<cstdio> using namespace std; int f[10000],n,m,a[110]; int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);f[0]=1;for(int i=1;i<=n;i++)for(int j=m;j>=a[i];j--)f[j]+=f[j-a[i]];printf("%d",f[m]); }
01背包求方案数
三、区间型dp
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int w[101],f[101][101],sum[101]; int n; int main() {scanf("%d",&n);for(int i=1; i<=n; i++) {scanf("%d",&w[i]);sum[i]=sum[i-1]+w[i];}for(int i=2; i<=n; i++)for(int j=i-1; j>=1; j--) {f[j][i]=0x3f3f3f3f;for(int k=j; k<i; k++)f[j][i]=min(f[j][i],f[j][k]+f[k+1][i]+sum[i]-sum[j-1]);}printf("%d\n",f[1][n]);return 0; }
合并果子
四、概率dp
#include<iostream> #include<cstdio> using namespace std; int n; double dp[1280][1280]; int main(){scanf("%d",&n);n/=2;for(int i=2;i<=n;i++)dp[i][0]=dp[0][i]=1.0;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) dp[i][j]=(dp[i-1][j]+dp[i][j-1])/2.0;printf("%.4lf\n",dp[n][n]);return 0; }
搞笑世界杯
五、多维dp
#include<iostream> #include<cstdio> using namespace std; int n,m,x,maxx,s[5],qp[355],f[40][40][40][40]; int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&qp[i]);for(int i=1;i<=m;i++){scanf("%d",&x);if(x==1)s[1]++;if(x==2)s[2]++;if(x==3)s[3]++;if(x==4)s[4]++;}f[0][0][0][0]=qp[1];f[1][0][0][0]=qp[2];f[0][1][0][0]=qp[3];f[0][0][1][0]=qp[4];f[0][0][0][1]=qp[5];for(int i=0;i<=s[1];i++)for(int j=0;j<=s[2];j++)for(int l=0;l<=s[3];l++)for(int k=0;k<=s[4];k++){maxx=0;if(i)maxx=max(maxx,f[i-1][j][l][k]);if(j)maxx=max(maxx,f[i][j-1][l][k]);if(l)maxx=max(maxx,f[i][j][l-1][k]);if(k)maxx=max(maxx,f[i][j][l][k-1]);f[i][j][l][k]=maxx+qp[i+j*2+l*3+k*4+1];} printf("%d\n",f[s[1]][s[2]][s[3]][s[4]]);return 0; }
乌龟棋
整理的不全,noip不会考很难的吧。【逃
转载于:https://www.cnblogs.com/zzyh/p/7806263.html
【经典】Noip动态规划相关推荐
- 13.最为经典的动态规划入门
一.动态规划的简介 动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法. 动态规划背后的基本思想非常简单.大致上,若要解一个给定问题,我们需要解其不同部分(即 ...
- 几个经典的动态规划算法
一.动态规划基本思想 一般来说,只要问题可以划分成规模更小的子问题,并且原问题的最优解中包含了子问题的最优解,则可以考虑用动态规划解决.动态规划的实质是分治思想和解决冗余,因此,动态规划是一种将问题实 ...
- 五大经典算法-动态规划 及其算法应用
前言 整篇文章分析整个动态规划算法,什么是动态规划,及动态规划算法在字符串匹配中使用.分治法的差别点.动态规划优点: 概念 什么叫做动态规划(dynamic programming),它是运筹学的一个 ...
- JZOJ 3418. 【NOIP动态规划专题】选课
Description 大学里实行学分.每门课程都有一定的学分,学生只要选修了这门课,并通过考核就能获得相应的学分.学生最后的学分是他各门课学分的总和.每个学生都要选择规定数量的课程.其中有些课程可以 ...
- 经典动态规划————背包九讲
前言 本篇文章是我(dd_engi)正在进行中的一个雄心勃勃的写作计划的一部分,这个计划的内容是写作一份较为完善的NOIP难度的动态规划总结,名为<解动态规划题的基本思考方式>.现在你看到 ...
- c++ 多重背包状态转移方程_动态规划入门——详解经典问题零一背包
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是周三算法与数据结构专题的第12篇文章,动态规划之零一背包问题. 在之前的文章当中,我们一起探讨了二分.贪心.排序和搜索算法,今天我们来 ...
- 五大经典算法(贪婪、动态规划、分治、回溯、分支限界法)及其联系和比较
一.贪心法 贪心算法的含义: 贪心算法(也叫贪婪算法)是指在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解.贪心算法不是对所有问题都能得 ...
- 动态规划入门——详解经典问题零一背包
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是周三算法与数据结构专题的第12篇文章,动态规划之零一背包问题. 在之前的文章当中,我们一起探讨了二分.贪心.排序和搜索算法,今天我们来 ...
- 动态规划经典题目总结
微信公众号 在算法中,动态规划题目算是比较经典的一类题目.在找工作中,不管是笔试,还是面试,我们经常会遇到用动态规划来解决问题的情况,有时候面试官还需要我们现场手写出动态规划解法的代码.因此,在求职中 ...
最新文章
- ComboBox自动补全小技巧
- 李宏毅机器学习(二)自注意力机制
- 29 | 如何判断一个数据库是不是出问题了?
- 做网管这么久了,每个月只是拿1000元的工资
- MTK PerfService介绍
- 开关造成的毛刺_干冰清洗机模具清洗机干冰去毛刺机注意事项
- 默认大小_如何更改 Linux 控制台字体类型和大小 | Linux 中国
- matplotlib可视化学习笔记
- 移动计算的未来:是什么在推动变革? | 幂集创新
- Linux转发性能评估与优化 转发瓶颈分析与解决方案
- 12000字解读元气森林:套利与降维的游戏
- Java学习篇之I/O篇
- 设计师的色彩搭配指南
- 快速理解三角函数:积化和差、和差化积
- 线性电路特性的研究与multisim仿真(附工程文件)
- 为了理想,因为爱情-开课第一天有感(鸡汤向)
- 关于数据清洗的常见方式
- Hdu 5172 GTY's gay friends
- Python —— Numpy数组组合
- 一系列令人敬畏的.NET核心库,工具,框架和软件
热门文章
- python程序运行结果始终为0_Python:始终运行程序
- R语言实现混频数据分析
- 话题:什么是前端工程化?
- php 什么cms能让会员自已建个独立站并绑上二级域名?,CMS_帝国CMS使用二级域名并解决顶一下的方法,1、将2级域名解析指向到所在 - phpStudy...
- 根目录_ubuntu 18.04 server版根目录只有4G?
- gsea富集分析结果怎么看_简单的GSEA分析
- ocx控件 postmessage消息会消失_通过HackerOne漏洞报告学习PostMessage漏洞实战场景中的利用与绕过...
- Oracle完全手册,Oracle_11g+Oracle Sqldeveloper 安装完全手册(for win 7 64x)
- SpringBoot中模板引擎thymeleaf
- Spring中IoC创建对象方式(构造器注入)