。。。。注释写在代码里了。
既然是求最小的天数,应该以天数作为DP值,剩下的变量里挑选合适的作为数组下表(数据范围可能会有提示)
/*定义一个dp[j][k]表示从前开始,拿到了第j个了,
当前最后一个背包剩下k的空间,此时的最小背包数量
转移分两种,一个是当前背包还能塞下第j个就塞,
一个塞不下了,新开一个背包,枚举当前背包的剩余空间,转移。
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define re register
using namespace std;
const int N = 3005;
int n,m,f[N][200],a[N],minn[N];
inline int read()
{
char c=getchar();
int ans=0,w=1;
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') { w=-1; c=getchar(); }
while(c>='0'&&c<='9')
{ ans=ans*10+c-'0'; c=getchar(); }
return ans*w;
}
int main()
{
n=read(); m=read();
for(re int i=1;i<=n;i++)
a[i]=read();
memset(f,0x7f,sizeof(f));
if(n<m)
{ printf("You can't do it.\n"); return 0;}
f[0][119]=1;//
for(re int i=1;i<=n;i++) //在前i个物品中
for(re int j=min(m,i);j>=1;j--)//
{//原理同01背包的倒序
for(re int k=0;k<=119-a[i];k++)//
f[j][k]=min(f[j][k],f[j-1][k+a[i]]);//在原来的背包中添
for(re int k1=a[i]-1;k1>=0;k1--)
f[j][119-a[i]]=min(f[j][119-a[i]],f[j-1][k1]+1);//新加一个背包
}
int ans=0x3f3f3f3f;
for(int i=0;i<=119;i++)
ans=min(f[m][i],ans);
printf("%d\n",ans);
return 0;
}
原文:https://www.cnblogs.com/karryW/p/10827757.html