NOIP模板複習——經典動態規劃
阿新 • • 發佈:2018-12-30
揹包問題
0/1 揹包
n 為物品數,m 為揹包體積,v 為物品體積,w 為物品價值,f[i] 為體積為 i 的揹包能獲得的最大價值
for(i=1;i<=n;++i)
{
scanf("%d%d",&v,&w);
for(j=m;j>=v;--j)
f[j]=max(f[j],f[j-v]+w);
}
printf("%d",f[m]);
完全揹包
for(i=1;i<=n;++i)
{
scanf("%d%d",&v,&w);
for(j=v;j<=m;++j)
f[j]=max (f[j],f[j-v]+w);
}
printf("%d",f[m]);
混合揹包和多重揹包只是和上面的變了一下形,就不說了
二維揹包
每件物品有兩種費用,u 和 v,答案就在兩種費用的上限中
for(i=1;i<=n;++i)
{
scanf("%d%d%d",&u,&v,&w);
for(j=x;j>=u;--j)
for(k=y;k>=v;--k)
f[j][k]=max(f[j][k],f[j-u][k-v]+w);
}
分組揹包
為每件物品所在的組, 為第 組的物品數量, 為總組數, 就是把物品記下來
for(i=1;i<=n;++i)
{
scanf("%d%d%d",&v[i],&w[i],&s);
if(!num[s]) t++;
rec[s][++num[s]]=i;
}
for(k=1;k<=t;++k)
{
for(j=m;j>=0;--j)
{
for(i=1;i<=num[k];++i)
{
if(j<v[rec[k][i]]) continue;
f[j]=max(f[j],f[j-v[rec[k][i]]]+w[rec[k][i]]);
}
}
}
最長上升子序列
可以用二分實現,時間複雜度
是原序列, 是序列長度, 是最長上升子序列的長度
d[k=1]=a[1];
for(i=2;i<=n;++i)
{
if(d[k]<a[i]) d[++k]=a[i];
else d[lower_bound(d+1,d+k+1,a[i])-d]=a[i];
}
printf("%d",k);
最長公共子序列
兩個串分別是 A 和 B,其中 n 是 A 的長度,m 是 B 的長度
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
{
if(A[i]==B[j]) f[i][j]=f[i-1][j-1]+1;
else f[i][j]=max(f[i-1][j],f[i][j-1]);
}
}
printf("%d",f[n][m]);
最長公共上升子序列
B[0]=-inf;
for(i=1;i<=n;++i)
{
if(B[0]<A[i]) num=f[i-1][0];
for(j=1;j<=m;++j)
{
if(A[i]==B[j]) f[i][j]=num+1;
else f[i][j]=f[i-1][j];
if(B[j]<A[i]) num=max(num,f[i-1][j]);
}
}
int ans=-inf;
for(i=1;i<=m;++i)
ans=max(ans,f[n][i]);
printf("%d",ans);