01背包的两种写法

普通写法:

普通的我就不详细解释了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
int n,vol;
struct spe
{
    int value,vol;
};
spe p[1005];
int dp[1005];
int main()
{
    int T;
    scanf("%d",&T);
    while( T-- )
    {
        scanf("%d %d",&n,&vol);
        for( int i = 1 ; i <= n; i++ )
        {
            scanf("%d",&p[i].value);
        }
        for( int i = 1 ; i <= n; i++ )
        {
            scanf("%d",&p[i].vol);
        }
        memset(dp,0,sizeof dp);
        for( int i = 1 ; i <= n ; i++ )
        {
            for( int j = vol ; j >= p[i].vol ; j-- )
            {
                dp[j] = max( dp[j],dp[j-p[i].vol]+p[i].value );
            }
        }
        cout<<dp[vol]<<endl;
    }
    return 0;
}
/*

1 2
1 7
1 3
1 4
1 9
3



*/

第二种写法:

当然,它也有它的使用范围拉,当价值的范围很小的时候才能用这个,而且用这个算法,它的复杂度和背包容量没有关系,所以说我们是根据价值来写的。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#define ll long long
using namespace std;
ll dp[10000005];
ll val[105],v[105];
ll T,n,m;
 
int main()
{
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&m);
        int sum = 0;
        for(int i=0;i<n;i++)
        {
           scanf("%lld%lld",&v[i],&val[i]);
           sum += val[i];
        }
        memset(dp,0x3f3f3f3f,sizeof(dp));
        dp[0] = 0;        //一定不能省略   
        for(int i=0;i<n;i++)
           for(int j=sum;j>=val[i];j--)
              dp[j] = min(dp[j], dp[j - val[i]] + v[i]);
          
        // int ans = -1;
        for(int i=sum;i>=0;i--)
        {
            if(dp[i] <= m)
            {
                printf("%d\n",i);
                break;
            }
        }
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39627843/article/details/80956551