关于本题数学问题的证明
前言:
看到人多人说本题数据很水所以背包能跑过,其实不然。背包能过是存在数学严谨的时间复杂度证明的。本篇题解来解决这个证明问题。
题意:
给你
解释:
第一眼看过,我的题意翻译和原题不同,先说序列元素能否为负数:用原题的背景说,当任一原木材长度小于等于
证明思路:
欲证原命题,即证存在一个数,满足大于等于它的数都能被表示。先拿出一个序列看:
考虑这个序列能表示哪些数,举个简单的例子:
有了这个结论后,在推广就得到了一般性结论,也就是上上述序列能表示:
也就是:当
时间复杂度
使用无限背包,枚举木头
代码
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
register int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<3)+(x<<1)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(int X)
{
if(X<0) {X=~(X-1); putchar('-');}
if(X>9) write(X/10);
putchar(X%10+'0');
}
int n,m,l[(int)1e2+(int)1e1],f[(int)9e6+(int)1e1],minx=1e3;
int chu(int x,int y){
if(x%y==0)return x/y;
return x/y+1;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;++i){
l[i]=read();
if(l[i]<=m){
write(-1); return 0;
}
minx=min(minx,l[i]-m);
}
minx=chu(minx,m)*minx-1; f[0]|=1;
for(int i=1;i<=n;++i){
for(int h=l[i]-m;h<=l[i];++h){
for(int v=h;v<=minx;++v){
f[v]=max(f[v],f[v-h]);
}
}
}
for(int i=minx;i>=1;--i){
if(f[i]==0){
write(i); return 0;
}
}
write(-1);
return 0;
}
注:
本篇题解关键在于背包时间复杂度的论述证明,算法固然不好。
AC记录