2021-05-09

ACM学习总结之背包问题

这周学习了背包问题。
背包问题属于一种线性规划的模型。它可分为好几类。包括01背包,完全背包等问题。
01背包:有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
设f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值,则可得状态转移方程f[i][v]=max{f[i-1][v],f[i-1][v-c[i]]+w[i]};由于对于每一个下标为i的状态,它的值仅有它的上一个下标为i-1的状态决定,则可进行空间优化,得到 f[v]=max{f[v],f[v-c[i]]+w[i]};需要注意的是,对一维数组进行遍历是容量逆序遍历,只有逆序遍历,才能保证第i件物品时方程中
f[v-c[i]]是对应i-1物品的值。
代码

#include<iostream>
using namespace std;
#define MAX_N 3500
#define MAX_V 20000
struct good
{
    int c;
    int w;
}goods[MAX_N];
int main()
{
    int i,j;
    int n,v;
    int f[MAX_V];
    while(cin>>n>>v)
    {
        for(i=0;i<=v;i++)f[i]=0;
        for(i=0;i<=n;i++)cin>>goods[i].c>>goods[i].w;
        for(i=0;i<=n;i++)
        {
            for(j=v;j>=goods[i].c;j--)
            {
                   if(f[j]<f[j-goods[i].c]+goods[i].w)
                   f[j]=f[j-goods[i].c]+goods[i].w;
            }
        }
        cout<<f[v]<<endl;
    }
    return 0;
}


完全背包:
有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
与01背包不同的是每件物品的数量不限定只要小于背包空间可随便取,得到的状态转移方程为f[i][j]=max{f[i-1][j-kw[i]]+kv[i]|0=<k<=V/w[i]}。
代码:

for(int i=1;i<=n;i++)
             {
                for(int j=0;j<=V;j++)
                {
                   f[i][j]=f[i-1][j];
                  for(int k=0;k<=V/v[i];k++)
                   {
                     if(j-k*v[i]>=0)
                     {
                        f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*c[i]);
                      }
                     }
                  }
                  }
                  int ans=0;
                  for(int i=0;i<=V;i++)
                    ans=max(ans,f[n][i]);
                  printf("%d\n",ans);

优化后得到f[i][v]=max{f[i-1][v],f[i][v-c[i]]+w[i]};代码为

for(int i=1;i<=n;i++)
      {
         for(int j=0;j<=V;j++)
         {
            if(j-v[i]>=0)
            f[j]=max(f[j],f[j-v[i]]+c[i]);
          }
       }
     printf("%d\n",f[n]);

题目:
Recently, iSea went to an ancient country. For such a long time, it was the most wealthy and powerful kingdom in the world. As a result, the people in this country are still very proud even if their nation hasn’t been so wealthy any more.
The merchants were the most typical, each of them only sold exactly one item, the price was Pi, but they would refuse to make a trade with you if your money were less than Qi, and iSea evaluated every item a value Vi.
If he had M units of money, what’s the maximum value iSea could get?
题意:有n个商品,你有一定的钱,每件商品都有其价格、价值及其购买的前提资金。你的金钱必须大于商品的前提资金才能买那个商品。求获得的最大价值。此题为01背包的变形,与01背包的区别为商品多了个前提资金,为了尽可能多的获得价值,先对商品的前提资金排序,便转换成了01背包问题。
代码:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
using namespace std;
struct node
{
	const bool operator<(const node&rhs)const {
		return m < rhs.m;
	}
	int a, b, c;
	int m;
};
node s[5050];
int dp[5050];
int main() {
	int N, M;
	while (scanf("%d %d", &N, &M) != EOF) {
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= N; i++) {
			scanf("%d %d %d", &s[i].a, &s[i].b, &s[i].c);
			s[i].m = s[i].b - s[i].a;
		}
		sort(s, s + N);
		for (int i = 1; i <= N; i++) {
			for (int j = M; j >= s[i].a; j--) {
				if (j >= s[i].b) {
					dp[j] = max(dp[j], dp[j - s[i].a] + s[i].c);
				}
			}
		}
		printf("%d\n", dp[M]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值