题解:一开始想到用类似背包DP的思路去DP,然而效率上无法接受。发现这一题虽然有两个空间限制,但是并不需要求最大值,需要维护的是能否凑出来。所以考虑放弃暴力枚举每一个空间,使用vector来存储每个可能的a[i]的和有哪些可能的b[i]的和,就能减少大量无谓的判断,大大优化效率,通过这道题。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,k,sa,sb,s,ss,sxa,sxb,ans;
int a[110],b[110];
bool f[10010][10010];
vector<int> Q[10010];
int main()
{
int x,y;
scanf("%d%d",&n,&k);ans=-1;
for(int i=1;i<=n;i++){scanf("%d",&a[i]);sa+=a[i];}
for(int i=1;i<=n;i++){scanf("%d",&b[i]);sb+=b[i];}
f[0][0]=1;s=min(sa-sa%k,sb*k);sa=sb=sxa=sxb=0;Q[0].push_back(0);
for(int i=1;i<=n;i++)
{
sa+=a[i];sb+=b[i];
sxa=min(sa,s);sxb=min(sb,s/k);
for(int j=sxa;j>=a[i];j--)
{
x=Q[j-a[i]].size();
for(int l=0;l<x;l++) if(!f[j][Q[j-a[i]][l]+b[i]])
{
y=Q[j-a[i]][l]+b[i];Q[j].push_back(y);
f[j][y]=1;if(j%y==0&&j/y==k) ans=max(ans,j);
}
}
}
printf("%d\n",ans);
return 0;
}