动态规划:背包dp

01背包题目
问题描述:有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
特点:每种物品仅有一件,可以选择放或不放。

//dp[i][j]表示前i件物品恰放入一个容量为j的背包可以获得的最大价值
①for(int i =1;i<=n;i++)
{
	for(int j=1;j<=V;j++) dp[i][j]=dp[i-1][j]; 
	for(int j=weight[i];j<=V;j++)
	{
		dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
	}
}
②int now=1,pre=0;
for(int i=1;i<=n;i++)
{
	for(int j=weight[i];j<=V;j++)
	{
		dp[now][j]=max(dp[pre][j],dp[pre][j-weight[i]]+value[i]);
	} 
}
③for(int i=1;i<=n;i++)
{
	for(int j=V;j>=weight[i];j--)
	{
		dp[j]=max(dp[j],dp[j-weigth[i]]+value[i];
	}
}

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

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3+5;
int main()
{
	int n,m;
	int dp[maxn],a[maxn];
	while(cin>>n)
	{
		if(n==0) break;
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		sort(a+1,a+1+n);
		cin>>m;
		if(m<5)
		{
			cout<<m<<endl;
			continue;
		}
		for(int i=1;i<n;i++)
		{
			for(int j=m-5;j>=a[i];j--)
			{
				dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
			}
		} 
		cout<<m-dp[m-5]-a[n]<<endl;
	}
} 

HDU1171:BigEvent in HDU
http://acm.hdu.edu.cn/showproblem.php?pid=1171

#include <bits/stdc++.h>
using namespace std;
int val[5005],dp[255555];
int n,i,j,a,b,l,sum;
int main()
{
    while(~scanf("%d",&n)&&n>0)
    {
        memset(val,0,sizeof(val));
        memset(dp,0,sizeof(dp));
        sum = 0;
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&a,&b);
            for(int i=0;i<b;i++)
            {
                val[i]=a;//将价值存入数组
                sum+=a;
            }
        }
        for(i=0;i<l;i++)
        {
            for(j=sum/2;j>=val[i];j--)//01背包
            {
                dp[j]=max(dp[j],dp[j-val[i]]+val[i]);
            }
        }
        printf("%d %d\n",sum-dp[sum/2],dp[sum/2]);
    }
    return 0;
}

HDU2602:BoneCollector (模板题)
http://acm.hdu.edu.cn/showproblem.php?pid=2602

#include<bits/stdc++.h>
using namespace std;
int i,j,k,t,n,m,v;
int dp[1006],c[1006],w[1006];
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&v);
        for(i=1;i<=n;i++)
            scanf("%d",&w[i]);
        for(i=1;i<=n;i++)
            scanf("%d",&c[i]);
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
            for(j=c[i];j<=v;j++)
            {
            	dp[j]=max(dp[j],dp[j-c[i]]+w[i]);
            }
            for(k=1;k<=v;k++)
                printf("%d ",dp[k]);
            printf("\n");
        }
        printf("%d\n",dp[v]);
    }
    return 0;
}

HDU2639:BoneCollector II(01背包第k优解)
http://acm.hdu.edu.cn/showproblem.php?pid=2639

HDU2955:Robberies
http://acm.hdu.edu.cn/showproblem.php?pid=2955

HDU3466:ProudMerchants
http://acm.hdu.edu.cn/showproblem.php?pid=3466

HDU1864:最大报销额
http://acm.hdu.edu.cn/showproblem.php?pid=1864

完全背包题目
题目描述:有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

//完全背包 
for(int i=1;i<=n;i++)
{
	for(int j=weight[i];j>=V;j++)//当前状态能从上一个状态转移过来,所以是正遍历
	{
		dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
	}
}

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

#include<bits/stdc++.h>
using namespace std;
const int N=1000000+50,inf=1e9+7;
int  t,x,y,n,W;
int v[N],w[N],dp[N];
int main()
{
    scanf("%d",&t);
    while(t--)
	{
        scanf("%d%d",&x,&y);
		W=y-x;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) 
		{
			scanf("%d%d",&v[i],&w[i]);
		}
        for(int i=1;i<=W;i++) 
		{
			dp[i]=inf;
			for(int i=1;i<=n;i++)
			{
            	for(int j=w[i];j<=W;j++)
            	{
            		dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
				}	
       		 }
		}
        if(dp[W]!=inf) printf("The minimum amount of money in the piggy-bank is %d.\n",dp[W]);
        else printf("This is impossible.\n");
    }
    return 0;
}

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

#include<iostream>
using namespace std;
int value[3]={150,200,350};
int main()
{
    int T;
    while(~scanf("%d",&T) &&T!= 0)
    {
        int dp[10001];
        int n;
        for(int i=0;i<T;i++)
        {
            scanf("%d", &n);
            memset(dp, 0, sizeof(dp));
            for(int j=0; j<3;j++)   
            {
                for(int k=value[j]; k<=n;k++)       
                {
                    dp[k]=max(dp[k],dp[k-value[j]]+value[j]);
                }      
            }
            printf("%d\n",n-dp[n]);  
        }
    }
    return 0;
}

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

#include <iostream>
#include <cstring>

using namespace std;

int a[105], b[105], dp[105][105];

int main()
{
    int n, m, k, s;
    while(cin >> n >> m >> k >> s)
    {
        for(int i = 0; i < k; ++i)
            cin >> a[i] >> b[i];
            
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < k; ++i)
            for(int j = 1; j <= s; ++j)
                for(int p = b[i]; p <= m; ++p)
                    dp[p][j]= max(dp[p][j], dp[p-b[i]][j-1]+a[i]);
        if(dp[m][s] < n)
            cout << "-1" << endl;
        else
        {
            for(int i = 0; i <= m; ++i)
            {
                if(dp[i][s] >= n)
                {
                    cout << m-i << endl;
                    break;
                }
            }
        }
    }
    return 0;
}

多重背包
问题描述:有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
这题目和完全背包问题很类似。基本的方程只需将完全背包问题的方程略微一改即可,因为对于第i种物品有n[i]+1种策略:取0件,取1件……取 n[i]件。令f[i][v]表示前i种物品恰放入一个容量为v的背包的最大权值,则:f[i][v]=max{f[i-1][v-kc[i]]+ kw[i]|0<=k<=n[i]}。复杂度是O(V*∑n[i])。

for(int i=1;i<=n;i++)
{
	for(int j=weight[i];j<=V;j++)
	{
		for(int k=V;k>=j*weight[i];k--)
		{
			dp[i][k]=max(dp[i-1][k],dp[i-1][k-j*weight[i]]+j*value[i]);
		}
	}
}

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

#include<bits/stdc++.h>
using namespace std;
const int maxn=500;
int n,m,w[maxn],c[maxn],num[maxn],dp[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
	int cur=0;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	    scanf("%d%d%d",&w[i],&c[i],&num[i]);
	int ans=0;
	memset(dp,0,sizeof(dp));
	for(int i=0;i<m;i++)
	{
	    for(int j=w[i];j<=n;j++)
	    {
		for(int k=1;k<=num[i];k++)
		    if(j>=k*w[i])
			dp[j]=max(dp[j],dp[j-k*w[i]]+c[i]*k);
		ans=max(ans,dp[j]);
	    }
	}
	printf("%d\n",ans);	
    }
    return 0;
}

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

Poj 1014
http://poj.org/problem?id=1014

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值