牛牛的旅游纪念品
题目链接
这道题跟正常背包有点不一样,有点反向思维了
必须先枚举容量在枚举物品
f[i][j]
表示前i
个物品,满足任意两个的位置差都大于等于k
的容量为j
的背包的最大价值
必须逆向枚举,因为j
只与j-1
有关,而i与前边任意一个都可能有关,这里的i
虽然是第几个物品,但类似于正常背包问题中的体积
两种写法:
写法一:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=10010;
int f[N][110];//前i天选j个物品的最大价值
int a[N];
int n,m,k;
int main()
{
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)cin>>a[i];
memset(f,-0x3f,sizeof f);
for(int i=1;i<=n;i++)f[i][1]=max(f[i-1][1],a[i]);
for(int i=k+1;i<=n;i++)
{
for(int j=2;j<=m;j++)
{
f[i][j]=max(f[i-1][j],f[i-k][j-1]+a[i]);
}
}
cout<<f[n][m]<<endl;
}
写法二:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=10010;
int f[N][110];
int a[N];
int n,m,k;
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)cin>>a[i];
memset(f,-0x3f,sizeof f);
f[0][0]=0;
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
{
f[i][j]=f[i-1][j];
if(j==1)f[i][j]=max(f[i-1][j],a[i]);
if(i-k>=0) f[i][j]=max(f[i][j],f[i-k][j-1]+a[i]);
}
}
cout<<f[n][m]<<endl;
}