SDNU OJ上的几种背包问题

01背包问题  完全背包问题  多重背包问题:

1.1033 采药:

题目大意就是有M种草药可以采摘,每种草药只有一株,且每种草药价值为v,采摘所用时间为t, 现在小明有T(总时间)去采摘草药,问如何才能使采摘到的

草药总价值最大。

这是一个01背包问题

代码如下:

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<algorithm>  
using namespace std;    
int main()  
{  
	int max(int x,int y);
    int m,n;         
    int i,j;  
 	int t[101];  
  	int v[101];  
	int f[1001]={0}; 
    cin>>m>>n;   // time number
    for(i=1;i<=n;i++)  
    {   
        cin>>t[i]>>v[i];      //药时间   药价 
    }  
    for(i=n;i>0;i--)  //逆序处理 
    {  
        for(j=m;j>=t[i];j--)  
        {            
            f[j]=max(f[j],f[j-t[i]]+v[i]);  //转移方程          
        }  
    }  
    cout<<f[m]<<endl;  
    return 0;  
} 
int max(int x,int y)
{
	if(x>=y)
		return x;
	else if(x<y)
		return y;
}

类似的问题还有1175 开心的金明


2.1043.采药2;

题目大意与采药基本上一样,主要的区别就是该问题中每种草药的个数是无限多的,即意味着可以只采摘一种草药。

这是一个完全背包问题

代码如下:

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<algorithm>  
using namespace std;    


int t[1001];  
int v[1001];  
int f[1001]; 


int main()  
{  
	int max(int x,int y);
    int n,m;        // n总重  m总时间 
    int i,j;  
//  int t[1001];  
//  int v[1001];  
//	int f[1001]; 
    cin>>n>>m;   
    for(i=1;i<=m;i++)  
    {   
        cin>>t[i]>>v[i];      //药重   药价 
    }  
    for(i=1;i<=m;i++)  
    {  
        for(j=1;j<=n;j++)  
        {  
            if(t[i]<=j)  
            {  
                f[j]=max(f[j],f[j-t[i]]+v[i]);  //转移方程 
            }  
        }  
    }  
    cout<<f[n]<<endl;  
    return 0;  
} 
int max(int x,int y)
{
	if(x>=y)
		return x;
	else if(x<y)
		return y;
}

相似的题目有1360 DP(为啥不叫卡路里呢)


1061. 采药3

题目大意还是跟上面的差不多,但多了一种限制条件(每种药材质量,背包可承受最大重量),其实只要再加一层for循环就好了

这是一个多重背包问题

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;


int m,t,n;
int u[1005];
int w1[1005];
int w2[1005];
int v[1005];
int f[1005][1005];


int max(int x,int y)
{
	if(x>=y)
		return x;
	else 
		return y;
}


int main()    //二维费用背包
{
	cin>>m>>t>>n;
	int i;
	for(i=0 ; i<n; i++)
	{
		cin>>w1[i]>>w2[i]>>v[i];
	}
	for(int i = 1 ; i <= t ;i++) 			//表示背包可以不存储满
    {
		for(int j = 1 ; j <= m ;j++)
    	{
				f[i][j] = 0 ;  
		}
	}
	f[0][0]=0;
	for( i=0 ; i<n ; i++)
	{
		for(int T=t ;T>=w2[i]; T--)               // 多加了一层for循环
		{
			for(int M=m ; M>=w1[i]; M--)
			{
				f[T][M]=max(f[T-w2[i]][M-w1[i]] + v[i] , f[T][M]) ;		// 状态转移方程也相应的多了一个参数	
			}
		}	
	}
	cout<<f[t][m]<<endl;
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值