c语言算法—01背包问题(基础型)

来源:互联网 发布:win32 网络编程 编辑:程序博客网 时间:2024/05/22 14:29

01背包问题在动态规划中很是常见,那就只简略概述一下背包问题:

有一个背包,承重不能超过m千克,现有n件物品,都有其对应的质量与价值;要求在不超过最大承重的情况下,输出最大价值;

解决这个问题的最基础方式是使用二维数组;行数为其物品的个数(0行空出),列数为0-m;

每一次我们在进行填表时,每一个数都应该有两次填写机会,第一次令其等于其上一行同一列的数,而第一次进行更新,即计算此时的重量减去i的重量再加上i的价值和以前那个数谁大(这寓意着在此时背包的重量下拿出一部分再加上i本身的价值,看看是否能比不装i时更有价值);

下面,我们举出一个例子来看这个问题:
m=4;n=3;
w与p数组为:
w,p

构建而成的二维数组为:
二维数组

以下为代码:

#include<stdio.h>#include<string.h> #define max(a,b) (a>b? a:b)int m,n;int main(){    scanf("%d",&m);    scanf("%d",&n);    int w[n+1];    int p[n+1];    int c[n+1][m+1];    memset(c,0,sizeof(int)*(n+1)*(m+1));    for(int i=1;i<=n;++i)    scanf("%d%d",&w[i],&p[i]);    for(int i=1;i<=n;++i)    {        for(int j=0;j<=m;++j)        {            c[i][j]=c[i-1][j];            if(j-w[i]>=0)             c[i][j]=max(c[i][j],c[i-1][j-w[i]]+p[i]);        }    }    printf("%d",c[n][m]);    return 0;} 

值得注意的是,我们在创建二维数组时,可以选择横向创建,也可以创建竖向创建(i,j循环的先后不同而已),这个无影响;

但也可以选择从上至下创建,也可以选择由下至上创建;

这里选择由上至下创建,所以为i-1;如果是相反的,那么应该是i+1;

这里选择由上至下的原因,是考虑到空出来的那一行可以使得行标对齐w,p数组,也可以刚好避免开i-1超出数组边界的问题;同样,如果选择下至上,也要注意i+1的超界问题;

0 0