[DP]从01背包开始

来源:互联网 发布:淘宝手机充值怎么退款 编辑:程序博客网 时间:2024/06/18 01:39

01背包问题描述:

一堆物体有价值、费用,放入一定容量背包,要求价值最大。

状态转移方程:

f[i][j] = max{f[i-1][j], f[i-1][j-c[i]] + w[i]};

状态转移方程其实很好理解,f[i][j]代表把前i个物体选择放或不放入容量j的背包,最大价值。

最终答案就是f[n][v]


下面看一道经典题目:

hdu-2546 饭卡

http://acm.hdu.edu.cn/showproblem.php?pid=2546

AC代码:

#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int maxn = 1000+2;int c[maxn],f[maxn][maxn];int n,m;bool camp(int a,int b){return a>b;}int solve(){memset(c, 0, sizeof(c));for(int i = 1; i <= n; i++){scanf("%d", &c[i]);}scanf("%d", &m);if(m < 5){//特判什么都不能买的情况printf("%d\n",m);return 0;}if(n == 1){//特判printf("%d\n", m-c[1]);return 0;}m -= 5;sort(c+1, c+n+1,camp);//排序是01背包的关键 不排序的话费用较大的物品会阻断memset(f, 0, sizeof(f));
//状态转移
for(int i = n; i > 1; i--){
if(m < c[i]){for(int j = m; j >= 0; j--){f[i][j] = f[i+1][j];}}for(int j = m; j >= c[i]; j--){f[i][j] = max(f[i+1][j], f[i+1][j-c[i]] + c[i]);}}m += 5;m -= f[2][m-5];m -= c[1];printf("%d\n", m);return 0;}int main(){//程序入口判断输入结束while(scanf("%d",&n) && n)solve();return 0;}


0 0
原创粉丝点击