【模板整合计划】DP动态规划
【模板整合计划】DP动态规划
一:【背包】
1.【01背包】
#include<algorithm>
#include<cstdio>
int T,n,i,j,v[110],w[110],f[1010];
int main(){
scanf("%d%d",&T,&n);
for(i=1;i<=n;i++)scanf("%d%d",&v[i],&w[i]);
for(i=1;i<=n;i++)
for(j=T;j>=v[i];j--)
f[j]=std::max(f[j],f[j-v[i]]+w[i]);
printf("%d",f[T]);
}
2.【完全背包】
#include<bits/stdc++.h>
using namespace std;
int T,n,ans,a[105],dp[30005];
int main(){
scanf("%d",&T);
while(T--){
memset(dp,-127,sizeof(dp));
scanf("%d",&n);dp[0]=ans=0;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=a[i];j<=25000;j++)
dp[j]=max(dp[j],dp[j-a[i]]+1);
for(int i=1;i<=n;++i)ans+=dp[a[i]]==1;
printf("%d\n",ans);
}
}
3.【多人背包】
#include<algorithm>
#include<cstring>
#include<cstdio>
int ans,T,n,i,j,k,K,a,b,t,re[45],v[210],w[210],f[5010][45];
int main(){
scanf("%d%d%d",&K,&T,&n);
memset(f,-127,sizeof(f));f[0][1]=0;
for(i=1;i<=n;i++)scanf("%d%d",&v[i],&w[i]);
for(i=1;i<=n;i++)
for(j=T;j>=v[i];j--){
a=b=1,t=0;
while(t<=K)
if(f[j][a]>=f[j-v[i]][b]+w[i])re[++t]=f[j][a++];
else re[++t]=f[j-v[i]][b++]+w[i];
for(k=1;k<=K;k++)f[j][k]=re[k];
}
for(i=1;i<=K;i++)ans+=f[T][i];
printf("%d",ans);
}
4.【分组背包】
#include<algorithm>
#include<cstdio>
using namespace std;
int T,n,i,j,a[65],s,t,r1,r2,r[65][3],v[65],w[65],f[32010];
int main(){
scanf("%d%d",&T,&n);
v[0]=0xfffffff;
for(i=1;i<=n;i++){
scanf("%d%d%d",&v[i],&s,&a[i]);
if(a[i])r[a[i]][++r[a[i]][0]]=i;w[i]=v[i]*s;
}
for(i=1;i<=n;i++)
for(j=T;j>=v[i]&&(!a[i]);j--){
t=j-v[i],r1=r[i][1],r2=r[i][2];
f[j]=max(f[j],f[t]+w[i]);
if(v[r1]<=t)f[j]=max(f[j],f[t-v[r1]]+w[i]+w[r1]);
if(v[r2]<=t)f[j]=max(f[j],f[t-v[r2]]+w[i]+w[r2]);
if(v[r1]+v[r2]<=t)f[j]=max(f[j],f[t-v[r1]-v[r2]]+w[i]+w[r1]+w[r2]);
}
printf("%d",f[T]);
}
5.【多重背包】
#include<algorithm>
#include<cstring>
#include<cstdio>
#define Re register int
using namespace std;
const int N=103,M=4e4+3;
int n,m,x,y,z,V,ans,v[N*17],w[N*17],dp[M];
inline void in(Re &x){
Re fu=0;x=0;char ch=getchar();
while(ch<'0'||ch>'9')fu|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=fu?-x:x;
}
int main(){
in(m),in(V);
memset(dp,-127,sizeof(dp));
dp[0]=0;
while(m--){
in(x),in(y),in(z);Re p=1;
while(z>=p)v[++n]=y*p,w[n]=x*p,z-=p,p<<=1;
if(z)v[++n]=y*z,w[n]=x*z;
}
for(Re i=1;i<=n;++i)
for(Re j=V;j>=v[i];--j)
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
for(Re i=0;i<=V;++i)ans=max(ans,dp[i]);
printf("%d\n",ans);
}
6.【混合背包】
#include<algorithm>
#include<cstdio>
using namespace std;
int x,a,b,c,d,T,n,i,j,t,f[1010],v[100010],w[100010];
int main(){
scanf("%d:%d%d:%d%d",&a,&b,&c,&d,&n);
T=c*60+d-a*60-b;
for(i=1;i<=n;i++){
scanf("%d%d%d",&a,&b,&c);
if(!c){
for(j=0;j+a<=T;j++)
f[j+a]=max(f[j+a],f[j]+b);
continue;
}
x=1;
while(c>=x){v[++t]=x*a,w[t]=x*b,c-=x,x<<=1;}
v[++t]=c*a,w[t]=c*b;
}
for(i=1;i<=t;i++)
for(j=T;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+w[i]);
printf("%d",f[T]);
}
7.【二维费用】
#include<algorithm>
#include<cstdio>
using namespace std;
int tmp,T1,T2,x,y,n,i,j,k,v1[105],v2[105],w[105],dp[105][105],ans[105][105];
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d%d%d",&v1[i],&v2[i],&w[i]);
scanf("%d%d",&T1,&T2);
for(i=1;i<=n;++i)
for(j=T1;j>=v1[i];--j)
for(k=T2;k>=v2[i];--k)
if(dp[j][k]<(tmp=dp[j-v1[i]][k-v2[i]]+1)){
dp[j][k]=tmp;
ans[j][k]=ans[j-v1[i]][k-v2[i]]+w[i];
}
else if(dp[j][k]==tmp)ans[j][k]=min(ans[j][k],ans[j-v1[i]][k-v2[i]]+w[i]);
printf("%d",ans[T1][T2]);
}
二:【树形DP】
#include<algorithm>
#include<cstring>
#include<cstdio>
#define R register int
using namespace std;
int head[6010],a,b,t,i,j,n,f[6010][2],pan[6010];
struct QAQ{int next,to;}Q[6010];
inline void add(int x,int y){Q[++t].to=y,Q[t].next=head[x],head[x]=t;}
inline void dfs(int w){
for(R k=head[w];k;k=Q[k].next){
int to=Q[k].to;
dfs(to);
f[w][0]+=max(f[to][0],f[to][1]);
f[w][1]+=f[to][0];
}
}
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&f[i][1]);
for(i=1;i<n;i++)scanf("%d%d",&a,&b),pan[a]++,add(b,a);
for(i=1;i<=n;i++)
if(!pan[i]){
dfs(i);
printf("%d\n",max(f[i][0],f[i][1]));
return 0;
}
}
- 【题解】
三:【数位DP】
\(Windy\) 数 \([SCOI2009]\) \([P2657]\)
1.【dfs】
#include<cstring>
#include<cstdio>
#include<cmath>
#define R register int
using namespace std;
int a,b,l,num[12],dp[12][10];
inline int dfs(int len,int up,int ok){
R i,ed,ans=0;
if(len<1)return 1;
if(!ok&&~dp[len][up]&&up!=-7)return dp[len][up];
ed=ok?num[len]:9;
for(i=0;i<=ed;i++)
if(abs(i-up)>=2)
ans+=dfs(len-1,(!i&&up==-7)?up:i,ok&&(i==ed));
if(!ok&&up!=-7)dp[len][up]=ans;
return ans;
}
inline int sovle(int x){
l=0;
while(x)num[++l]=x%10,x/=10;
return dfs(l,-7,1);
}
int main(){
scanf("%d%d",&a,&b);
memset(dp,-1,sizeof(dp));
printf("%d",sovle(b)-sovle(a-1));
}
2.【dp】
#include<cstdio>
#include<cmath>
#define R register int
using namespace std;
int i,j,k,a,b,l,ans,num[12],dp[12][10];
inline int dpp(int len){
ans=0;
for(i=1;i<len;i++)
for(j=1;j<10;j++)
ans+=dp[i][j];
for(j=1;j<num[len];j++)ans+=dp[len][j];
for(i=len-1;i>0;i--){
for(j=0;j<num[i];j++)
if(abs(num[i+1]-j)>=2)ans+=dp[i][j];
if(abs(num[i]-num[i+1])<2)break;
}
if(!i)ans++;
return ans;
}
inline int sovle(int x){
l=0;
while(x)num[++l]=x%10,x/=10;
return dpp(l);
}
inline int sakura(){
scanf("%d%d",&a,&b);
for(i=0;i<10;i++)dp[1][i]=1;
for(i=2;i<11;i++)
for(j=0;j<10;j++)
for(k=0;k<10;k++)
if(abs(j-k)>=2)
dp[i][j]+=dp[i-1][k];
printf("%d",sovle(b)-sovle(a-1));
}
int QAQWQ=sakura();
int main(){}
四:【DP 的优化】
1.【二分】
#include<bits/stdc++.h>
using namespace std;
int pan[100010],b[100010],f[100010],n,i,a,len=1,l,r,mid;
inline int in(){
int x=0,fh=1;char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x*fh;
}
int main(){
n=in();
for(i=1;i<=n;i++)a=in(),pan[a]=i,f[i]=0xfffffff;
for(i=1;i<=n;i++)a=in(),b[i]=pan[a];
f[1]=b[1];
for(i=2;i<=n;i++){
l=0;r=len;
if(b[i]>f[len])f[++len]=b[i];
else{
while(l<r){
mid=(l+r)/2;
if(f[mid]<b[i])l=mid+1;
else r=mid;
}
f[l]=min(b[i],f[l]);
}
}
printf("%d",len);
}
2.【矩阵乘法】
3.【二进制优化多重背包】
#include<algorithm>
#include<cstdio>
#define Re register int
using namespace std;
const int N=103,M=4e4+3,logN=17;
int m,n,x,y,z,V,ans,v[N*logN],w[N*logN],dp[M];
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
int main(){
in(m),in(V);
for(Re i=1;i<=m;++i){
in(x),in(y),in(z);
for(Re j=1;j<=z;j<<=1)z-=j,w[++n]=x*j,v[n]=y*j;
if(z)w[++n]=x*z,v[n]=y*z;
}
for(Re i=1;i<=n;++i)
for(Re j=V;j>=v[i];--j)
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
for(Re j=0;j<=V;++j)ans=max(ans,dp[j]);
printf("%d\n",ans);
}
4.【单调队列优化多重背包】
#include<cstdio>
#define Re register int
const int N=7003,M=7003;
int n,h,t,V,mp,tmp,v[N],w[N],c[N],Q[N],K[N],dp[M];
inline void in(Re &x){
Re fu=0;x=0;char ch=getchar();
while(ch<'0'||ch>'9')fu|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=fu?-x:x;
}
inline int max(Re a,Re b){return a>b?a:b;}
inline int min(Re a,Re b){return a<b?a:b;}
int main(){
in(n),in(V);
for(Re i=1;i<=n;++i)in(v[i]),in(w[i]),in(c[i]);
for(Re i=1;i<=n;++i)
for(Re r=0;r<v[i];++r){
h=1,t=0,mp=(V-r)/v[i];
for(Re p=0;p<=mp;++p){
tmp=dp[p*v[i]+r]-w[i]*p;
while(h<=t&&Q[t]<=tmp)--t;
Q[++t]=tmp,K[t]=p;
while(h<=t&&p-K[h]>min(c[i],V/v[i]))++h;
dp[p*v[i]+r]=max(dp[p*v[i]+r],Q[h]+p*w[i]);
}
}
printf("%d",dp[V]);
}
5.【斜率优化】
玩具装箱 \(\text{toy}\) \(\text{[P3195]}\)
#include<cstring>
#include<cstdio>
#define LL long long
#define Re register LL
const int N=5e4+5;
LL i,j,n,L,h=1,t=0,Q[N],S[N],dp[N];
//S[n]=∑C[i]+1, dp[i]=min(dp[j]+(S[i]-(S[j]+L+1))^2),++L
//dp[i]=S[i]^2-2*S[i]*L+dp[j]+(S[j]+L)^2-2S[i]*S[j]
//(2*S[i]) * S[j] + (dp[i]-S[i]^2+2S[i]L)=(dp[j]+(S[j]+L)^2)
// k * x + b = y
inline LL min(Re a,Re b){return a<b?a:b;}
inline LL X(Re j){return S[j];}
inline LL Y(Re j){return dp[j]+(S[j]+L)*(S[j]+L);}
inline long double slope(Re i,Re j){return (long double)(Y(j)-Y(i))/(X(j)-X(i));}//记得开long double
int main(){
scanf("%lld%lld",&n,&L);++L;
for(i=1;i<=n;S[i]+=S[i-1]+1,++i)scanf("%lld",&S[i]);
Q[++t]=0;//重中之重
for(i=1;i<=n;++i){
while(h<t&&slope(Q[h],Q[h+1])<=2*S[i])++h;//至少要有两个元素 h<t。出队判断时尽量加上等号
dp[i]=dp[j=Q[h]]+(S[i]-S[j]-L)*(S[i]-S[j]-L);
while(h<t&&slope(Q[t-1],Q[t])>=slope(Q[t-1],i))--t;//至少要有两个元素 h<t。入队判断时尽量加上等号
Q[++t]=i;
}
printf("%lld",dp[n]);
}
还有状压 \(DP\),区间 \(DP\) ,但写法多种多样,没有什么特定的模板额。
【模板整合计划】DP动态规划的更多相关文章
- 【模板整合计划】NB数论
[模板整合计划]NB数论 一:[质数] 1.[暴力判] 素数.コンテスト.素数 \(\text{[AT807]}\) #include<cstdio> #include<cmath& ...
- 【模板整合计划】图论—有向无环图 (DAG) 与树
[模板整合计划]图论-有向无环图 (DAG) 与树 一:[拓扑排序] 最大食物链计数 \(\text{[P4017]}\) #include<cstring> #include<cs ...
- 模板:插头dp
前言: 严格来讲有关dp的都不应该叫做模板,因为dp太活了,但是一是为了整理插头dp的知识,二是插头dp有良好的套路性,所以姑且还叫做模板吧. 这里先推荐一波CDQ的论文和这篇博客http://www ...
- Yii框架学习笔记(二)将html前端模板整合到框架中
选择Yii 2.0版本框架的7个理由 http://blog.chedushi.com/archives/8988 刚接触Yii谈一下对Yii框架的看法和感受 http://bbs.csdn.net/ ...
- Day 5 笔记 dp动态规划
Day 5 笔记 dp动态规划 一.动态规划的基本思路 就是用一些子状态来算出全局状态. 特点: 无后效性--狗熊掰棒子,所以滚动什么的最好了 可以分解性--每个大的状态可以分解成较小的步骤完成 dp ...
- LG4719 【模板】动态dp 及 LG4751 动态dp【加强版】
题意 题目描述 给定一棵\(n\)个点的树,点带点权. 有\(m\)次操作,每次操作给定\(x,y\),表示修改点\(x\)的权值为\(y\). 你需要在每次操作之后求出这棵树的最大权独立集的权值大小 ...
- wawawa8的模板复习计划
wawawa8的模板复习计划 数据结构 //手写堆 [link][https://www.luogu.org/problemnew/show/P3378] //并查集 [link][https://w ...
- (转)dp动态规划分类详解
dp动态规划分类详解 转自:http://blog.csdn.NET/cc_again/article/details/25866971 动态规划一直是ACM竞赛中的重点,同时又是难点,因为该算法时间 ...
- DP动态规划学习笔记——高级篇上
说了要肝的怎么能咕咕咕呢? 不了解DP或者想从基础开始学习DP的请移步上一篇博客:DP动态规划学习笔记 这一篇博客我们将分为上中下三篇(这样就不用咕咕咕了...),上篇是较难一些树形DP,中篇则是数位 ...
随机推荐
- python3匿名函数
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便. 在Python中,对匿名函数提供了有限支持.还是以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外, ...
- PMP备考-第二章-项目运行环境与项目经理
组织系统的三大因素:组织治理框架,管理要素和组织结构 组织治理和项目治理 组织治理 :组织中的重要决策制定框架,谁有权在什么时候用什么发放做出并推行什么重要决策. 项目治理 :组织为项目建立的高级别的 ...
- RPC 初识
RPC是什么 RPC(Remote Procedure Call) 释义是远程过程调用,常存在于分布式系统中. 比如说现在有两台服务器A, B,一个在A服务器上的应用想要调用B服务器上的应用提供的某个 ...
- Delphi-基础
一.Delphi 安装 1.1.快速启动程序,去掉加载开始欢迎页.在快捷方式--目标中添加路径 -pDelphi之后加 -np(例如,rcadero\Studio\20.p\bin\bds.exe&q ...
- 分母为0的坑(float)
分母不能为0 对于int 类型,如果分母为0,在程序运行时,会报错. 而对于float 类型,如果分母为0,则不会报错,而是会返回一个infinity(无穷大),也就是NAN. 因为除一个无穷小的数, ...
- XLM论文原理解析
1. 前言 近一年来,NLP领域发展势头强劲,从ELMO到LSTM再到去年最牛叉的Google Bert,在今年年初,Facebook又推出了XLM模型,在跨语言预训练领域表现抢眼.实验结果显示XLM ...
- Mysqldump一次备份多个指定数据库
今天碰到了,就作个记录. mysqldump -u user -p --databases DB1 DB2 --single-transaction --master-data=2 --default ...
- 201871010112-梁丽珍《面向对象程序设计(java)》第十五周学习总结
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...
- SQL-on-Hadoop 技术
SQL-on-Hadoop 技术 备注 Apache Hive Cloudera Impala Facebook Presto Apache Drill Spark SQL Apache Phoeni ...
- spark写入空值到Oracle
转自:https://blog.csdn.net/qq_33792843/article/details/83750025 val nullStr = org.apache.spark.sql.fun ...