【Algothrim】动态规划实例(0、1背包问题)

来源:互联网 发布:视频剪辑软件免费下载 编辑:程序博客网 时间:2024/05/25 20:00


//背包问题:有m件物品和一个承重为t的背包。第i件物品的重量是w[i],价值是v[i]。
//求解将哪些物品装入背包可使这些物品的重量总和不超过背包承重量t,且价值总和最大。

#include <stdio.h>
#include <conio.h>
#include <string.h>  

int f[1010],w[1010],v[1010];//f记录不同承重量背包的总价值,w记录不同物品的重量,v记录不同物品的价值

int max(int x,int y){//返回x,y的最大值
    if(x>y) return x;
    return y;

int main(){
    int t,m,i,j;
    memset(f,0,sizeof(f));  //总价值初始化为0
    scanf("%d %d",&t,&m);  //输入背包承重量t、物品的数目m
    for(i=1;i<=m;i++)
        scanf("%d %d",&w[i],&v[i]);  //输入m组物品的重量w[i]和价值v[i]
    for(i=1;i<=m;i++){  //尝试放置每一个物品
        for(j=t;j>=w[i];j--){
            f[j]=max(f[j-w[i]]+v[i],f[j]);
            //在放入第i个物品前后,检验不同j承重量背包的总价值,如果放入第i个物品后比放入前的价值提高了,则修改j承重量背包的价值,否则不变搜索
        }
    }

    printf("%d",f[t]);  //输出承重量为t的背包的总价值
    printf("\n");
    getch();
    return 0;
}


--------------------------------------------------------------------------------------------分割线-------------------------------------------------------------------------------------------------------------------------


定义

背包问题(Knapsack problem)是一种组合优化NP完全问题。问题可以描述为:

给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。

问题的名称来源于如何选择最合适的物品放置于给定背包中。相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V?它是在1978年由Merkel和Hellman提出的。

基本思路

01背包问题

这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:
f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。
那么分为两种情况:
1. 放入第i件物品(价值为f[i-1][v])
2. 不放入第i件物品(价值为f[i-1][v-c[i]]+w[i])

则其状态转移方程便是:
f[i][v]=max{f[i-1][v], f[i-1][v-c[i]]+w[i]}
可以压缩空间:
f[v]=max{f[v],f[v-c[i]]+w[i]}
也就是f[v]表示容量为v的背包可以获得的最大价值。

01背包代码
#include <iostream>    #define MAXSIZE 1000    using namespace std;    int f[MAXSIZE],c[MAXSIZE],w[MAXSIZE];//c是大小,w是价值    int main()    {        int N,V;//N为物品数,V表示背包大小        cin>>N>>V;        for (int i=0;i<N;i++)        {            cin>>c[i]>>w[i];        }        for (int i=0;i<N;i++)        {            for (int v = V; v >= c[i]; v--) //c[i]可优化为bound,bound = max {V - sum c[i,...n],c[i]}            {                f[v]=(f[v] > f[v - c[i]] + w[i])                    ? f[v]                    : f[v - c[i]] + w[i];//与状态转移公式f[v]=max{f[v],f[v-c[i]]+w[i]}等价            }        }        //当i=N时,可以跳出循环单独计算F[V]        cout << f[V] << '\n';    }

0 0
原创粉丝点击