蓝桥杯长期备赛

我以后不粘贴题目截图了,只贴一个链接,自己看去
就贴一个代码块,和自己一点注解

背包问题(前几个是DP用来熟练)

主要思想:相当粗糙的DP
题目传送门

#include<iostream>
using namespace std;
int c[1000013]={0};
int main(){
    
    int a,b;
    cin>>a>>b;
    c[a]=1,c[b]=1;//先标记一下 
    int maxans=max(a,b);//找出谁大谁小
    int ans=0; 
   /*这个for相当于遍历一次就好了*/
    for(int i=maxans+1;i<=a*b/*这里搞不懂,就是把范围搞大点就行了*/;i++){
        if(c[i-a]==1||c[i-b]==1){
            c[i]=1;
        }
        else
        ans=i;//记录最后一次不能表示的数,如果要优化的话,因该会提前break
    }
    cout<<ans;    
}

主要:就是dp,把 九个来源地 比较一下,注意初始化。这题就一个检测点,过的比较水

题目传送门

#include<iostream>
#include<algorithm>
using namespace std;
int c[103][103];
int ans[103][103]={0};
int main(){
	int a,b;
	cin>>a>>b;
	for(int i=1;i<=a;i++){
		for(int j=1;j<=b;j++){
			cin>>c[i][j];
		}
	}
	ans[1][1]=c[1][1];//切记DP初始化
	//接着把9个来源地比较一下,选出最大的
	for(int i=1;i<=a;i++){
		for(int j=1;j<=b;j++){
			if(i==1&&j==1)
			continue;//记得把第一个点跳过去
			int p=-10;//这个按理说应该开大一点
			if(i-1>=1)
			p=max(p,ans[i-1][j]);
			if(i-2>=1)
			p=max(p,ans[i-2][j]);
			if(i-3>=1)
			p=max(p,ans[i-3][j]);
			if(j-1>=1)
			p=max(p,ans[i][j-1]);
			if(j-2>=1)
			p=max(p,ans[i][j-2]);
			if(j-3>=1)
			p=max(p,ans[i][j-3]);
			if(i-1>=1&&j-1>=1)
			p=max(p,ans[i-1][j-1]);
			if(i-1>=1&&j-2>=1)
			p=max(p,ans[i-1][j-2]);
			if(i-2>=1&&j-1>=1)
			p=max(p,ans[i-2][j-1]);
			ans[i][j]=c[i][j]+p;//更新数据	 
		}
	}
	cout<<ans[a][b];
	
}

题目传送门

主要:就是再简单不过的01背包,老子却干了一中午!不多说。背包种类很多,我慢慢来吧。

特点就是 一个东西只能选或者不选


int dp[1003]={0},t[103],v[103];
    int a,b;
    cin>>a>>b;
    for(int i=1;i<=a;i++){//一个物品一个物品来 
        cin>>t[i]>>v[i];//边输入边处理数据 
        for(int j=b;j>=t[i];j--){//从大到小遍历体积,反向是因为,正向会覆盖以前的值 
        //和完全背包的区别就是它每次遍历都要把所有体积大小重新算一次。 
            dp[j]=max(dp[j-t[i]]+v[i],dp[j]);//这里的dp[j]都是上一 i循环 留下的值 
        }
    }
    cout<<dp[b];

题目传送门

主要:自己写的完全背包,一遍过,感觉很棒!!!!


int dp[1003]={0},t[1003],v[1003];
    int a,b;
    cin>>a>>b;
    for(int i=1;i<=a;i++){
        cin>>t[i]>>v[i];
        for(int j=t[i];j<=b;j++)//这里不用反向,和01背包代码差不多
            dp[j]=max(dp[j-t[i]]+v[i],dp[j]);
    }
    cout<<dp[b];

主要:自己写的多重背包,一遍过,感觉很棒!!!!

题目传送门


int w[103],v[103],s[103];
int dp[203];
	int a,b;
	cin>>a>>b;
	for(int i=1;i<=a;i++){
		cin>>w[i]>>v[i]>>s[i];//边输入边处理,相当于一个物品一个物品的处理 
		for(int j=b;j>=0;j--)/*枚举每种体积,不反向还不行,估计是因为也可能选到只拿一种的情况*/{
			for(int n=0;n<=s[i];n++)/*看某一种物品到底选几个,也就是比01背包多一个循环*/{
				if(j>=n*w[i])
				dp[j]=max(dp[j],dp[j-n*w[i]]+n*v[i]);
				else
				break//提高效率
			}
		}
	}
	cout<<dp[b];

题目传送门

混合背包

//简单点来说就是分为三种情况,对应01,完全,多重背包
int w[1003],v[1003],s[1003],dp[2003]={0};
	int a ,b;
	cin>>a>>b;
	for(int i=1;i<=a;i++){//每个物体 
		cin>>w[i]>>v[i]>>s[i];
		if(s[i]==0){//这里相当于完全背包 
			for(int j=w[i];j<=b;j++)
				dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
		}
		else if(s[i]==1){//这个是01背包 
			for(int j=b;j>=w[i];j--){
				dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
			}
		}	
		else//这个相当于多重背包
		for(int j=b;j>=0;j--){ 
			for(int p=0;p<=s[i];p++){//选几个 
				if(j>=p*w[i])
				dp[j]=max(dp[j],dp[j-p*w[i]]+p*v[i]);
        		else
        		break;//这个很关键,没有就容易超时
			}
		}
			
	}
	cout<<dp[b];

分组背包

题目传送门

int t[103],v[103],dp[103]={0};
	int a,b,c,e,f;
	cin>>a>>b;
	for(int i=1;i<=a;i++)/*一共a个组*/{
		cin>>c;/*每组物品数量*/
		//读取每组物品数据 
		for(int j=1;j<=c;j++){
			cin>>t[j]>>v[j];
		}
		/*相当于每个组里面用01背包*/
		for(int p=b;p>=0;p--)/*枚举体积*/{
			for(int q=1;q<=c;q++)/*一个组里的第几个物品*/{
				if(p>=t[q])
				dp[p]=max(dp[p],dp[p-t[q]]+v[q]); 
			}
		}
	}
	cout<<dp[b];

题目传送门

这个题比较考技术,我是抄的别人的,可以好好看看,就是两个背包

int w[2003],v[2003],dp1[10003]={0}/*这是不用魔法*/,dp2[10003]={0}/*这是用魔法*/;
	int a,b,k;
	cin>>a>>b>>k;
	for(int i=1;i<=a;i++){
		cin>>w[i]>>v[i];//牢记每次都是先枚举物体 
		for(int j=b;j>=w[i];j--){
			dp1[j]=max(dp1[j],dp1[j-w[i]]+v[i]);//更新不用魔法的dp
			if(j>=(w[i]+k))//这是准备用魔法
			dp2[j]=max(max(dp2[j],dp2[j-w[i]]+v[i])/*这是前面用过魔法了*/,
											dp1[j-w[i]-k]+2*v[i]/*这是没用过魔法*/);
		}
	}
	cout<<max(dp1[b],dp2[b]);

在这里插入图片描述

还有最后一个树状背包,先放一放,我估计肯定看不懂。
背包就先告一段落

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值