一道多重背包的问题,但是常规解法亲测超时,无优化TLE
通过二进制化化为 01 背包,将 O(V*N) 降为 O(V*logN)
79MS AC
#include <string.h>
#include <stdio.h>
#include <algorithm>
int s,n,max,a[111],x,y,z,i,k,j,dp[100005];
int main() {
while (scanf("%d", &s) != EOF) {
z = 0;
scanf("%d",&n);
for (i = 0; i < n; i++) {
scanf("%d%d", &x, &y);
k = 1; // 从 2^0开始
// 2进制优化转01背包
while (x>0) {
if(x>=k) {
a[z++] = k*y;
x -= k;
k = k<<1; // *2
}
else {
a[z++] = x*y;
break;
}
}
}
memset(dp, 0, sizeof(dp));
for(i=0; i<z; i++)
for(j=s; j>=a[i]; j--)
dp[j] = std::max(dp[j],dp[j-a[i]]+a[i]);
printf("%d\n",dp[s]);
}
return 0;
}
附常规解法:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main()
{
int cash,N,bill[12],me[12],dp[100001],i,j,k;
while(scanf("%d",&cash) != EOF) {
scanf("%d",&N);
if(cash == 0 || N == 0) {
printf("0\n");
continue;
}
for(i=0; i<N; i++)
scanf("%d%d", bill+i, me+i);
memset(dp, 0 ,sizeof(dp));
for(i=0; i<N; i++) {
for(j=cash; j>=me[i]; j--) {
for(k=1; k<=bill[i]; k++) {
if(j < k*me[i])
break;
dp[j] = max(dp[j-k*me[i]]+k*me[i],dp[j]);
}
}
}
printf("%d\n",dp[cash]);
}
return 0;
}