poj 1276(多重背包+最接近)

http://www.cnblogs.com/rainydays/archive/2013/03/08/2950258.html

http://www.cnblogs.com/ziyi--caolu/p/3216827.html

第一种:

邻接+统计数量

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!
")
#define MAXN 1010
#define MAX(a,b) a>b?a:b
#define blank pf("
")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f

int cash,n,sum;

int c[15],w[15],used[100005];

bool f[100005];

void mubag()
{
    int i,j;
    mem(f,false);
    f[0] = true;
    //debug;
    for(i=0;i<n;i++)
    {
        mem(used,0);
        for(j = w[i];j<=cash;j++)
        {
            if(f[j-w[i]] && !f[j] && used[j-w[i]]<c[i])
            {
                f[j] = true;
                used[j] = used[j-w[i]]+1;
                //pf("f%d cnt%d
",j,used[j]);
            }
        }
    }
}

int main()
{
    int i,j;
    while(~sf("%d%d",&cash,&n))
    {
        for(i=0;i<n;i++)
        {
            sf("%d%d",&c[i],&w[i]);
        }
        mubag();
        for(i=cash;i>=0;i--)
        {
            if(f[i])
            {
                pf("%d
",i);
                break;
            }
        }
    }
    return 0;
}

第二种:

二进制拆分+01背包

value = weight

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[110000],t[30000],s[2000][2];
int main()
{
    int cash,n;
    while(scanf("%d%d",&cash,&n)>0)
    {
         int cnt=0;
         //memset(t,0,sizeof(t));
         for(int i=1;i<=n;i++)
         {
                 scanf("%d%d",&s[i][0],&s[i][1]);
                 int k=1;
                 if(s[i][0]==0||s[i][1]==0)
                 continue;
                 while(s[i][0]-k>0)
                 {
                        t[cnt++]=k*s[i][1];
                        s[i][0]-=k;
                        k*=2;
                 }
                 t[cnt++]=s[i][0]*s[i][1];
         }
         memset(dp,0,sizeof(dp));
         for(int i=0;i<cnt;i++)
         {
                 for(int j=cash;j>=t[i];j--)
                 if(dp[j]<dp[j-t[i]]+t[i])
                 dp[j]=dp[j-t[i]]+t[i];
         }
         printf("%d
",dp[cash]);
    }
    return 0;
}

第三种:

完全背包+统计数量

value = weight

基本和第一种一样,速度也一样,更清晰一点

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int dp[110000],num[100100],s[2000][2];
int main()
{
    int cash,n;
    while(scanf("%d%d",&cash,&n)>0)
    {
         int cnt=0;
         for(int i=1;i<=n;i++)
         {
                 scanf("%d%d",&s[i][0],&s[i][1]);
         }
         memset(dp,0,sizeof(dp));
         for(int i=1;i<=n;i++)
         {
                 memset(num,0,sizeof(num));
                 for(int j=s[i][1];j<=cash;j++)
                 if(dp[j]<dp[j-s[i][1]]+s[i][1]&&num[j-s[i][1]]<s[i][0])
                 {
                        dp[j]=dp[j-s[i][1]]+s[i][1];
                        num[j]=num[j-s[i][1]]+1;
                 }
         }
         printf("%d
",dp[cash]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qlky/p/5639013.html