dp:0-1背包,扩展例题

这篇博客探讨了如何使用动态规划和回溯法解决两类信息技术问题:一是背包问题,涉及物品选择以最大化价值;二是时间规划问题,涉及在有限时间内完成多个任务。动态规划通过构建二维数组来确定最优解,而回溯法则通过递归尝试所有可能的解决方案。博客中提供了详细的代码实现,展示了这两种算法在实际问题中的应用。
摘要由CSDN通过智能技术生成

dp方法

#include<bits/stdc++.h>
using namespace std;
int wei[5]={ 0 , 2 , 3 , 4 , 5 };
int val[5]={ 0 , 3 , 4 , 5 , 6 };
int bagWei=8;
int dp[5][10]={0};
int item[5]={0};//表示第i个物品有没有被放进背包
void findWhat(int i,int j)
{
    if(i>=0){
        if(dp[i][j]==dp[i-1][j]){//没放i
            item[i]=0;
            findWhat(i-1,j);
        }
        else if(j-wei[i]>=0&&dp[i][j-wei[i]]+val[i]){
            item[i]=1;
            findWhat(i-1,j-wei[i]);
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    for(int i=1;i<5;i++){//第i个物品
        for(int j=1;j<=bagWei;j++){//背包现在容量
            if(j>=wei[i]){
                dp[i][j]=max(dp[i-1][j-wei[i]]+val[i],dp[i-1][j]);
            }
            else{
                dp[i][j]=dp[i-1][j];
            }
        }
    }
    for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 9; j++) {
			cout << dp[i][j] << ' ';
		}
		cout << endl;
	}
	//回溯找到应该装进去的东西
	findWhat(4,8);
	for(int i=1;i<5;i++){
        cout<<item[i]<<" ";
	}
	cout<<endl;
    return 0;
}

洛谷

#include<bits/stdc++.h>

using namespace std;
int len[5]={0};
int homework[25]={0};
int a[25][2000]={0};
int total=0;
int main()
{
    ios::sync_with_stdio(false);

    for(int i=1;i<=4;i++){
        cin>>len[i];
    }
    for(int i=1;i<=4;i++){
        int oneSum=0;//每门科目的时间总和
        for(int j=1;j<=len[i];j++){
            cin>>homework[j];
            oneSum+=homework[j];
        }
        int t1=0;
        for(int j=1;j<=len[i];j++){
            for(int k=0;k<=oneSum/2;k++){
                if(k<homework[j]){
                    a[j][k]=a[j-1][k];
                }
                else{
                    a[j][k]=max(a[j-1][k],a[j-1][k-homework[j]]+homework[j]);
                }
                t1=max(a[j][k],t1);
            }

        }
        total+=max(t1,oneSum-t1);
    }

    cout<<total<<endl;
    return 0;
}

dfs方法

原题传送

大致意思就是现在有不同级别的孔,也有不同级别的珠子,每种珠子都有放进去增值的上限,求怎么放这些珠子才能使现在拥有的价值最大。

#include<bits/stdc++.h>
#define MAXN 55
#define MAXS 305
#define MAXM 10005
using namespace std;

int n[MAXN];//孔的数量
int levNum[5]={0};//四个等级的孔的个数
int L[MAXM],p[MAXM],w[MAXM][MAXN];
int dp[MAXM][MAXS];
int m;

int DP()
{
    memset(dp,0,sizeof(dp));
    int ans=0;//最终装备里面放了toa个珠子的总价值
    int sum=0;//现在有的孔的总数量
    int tot=0;//放的珠子数量
    //先从等级高的往下枚举
    //因为等级为l的珠子能够装进l-4的孔里面,此时的l-4的孔都有了
    for(int l=4;l>=1;l--){
        sum+=levNum[l];
        for(int i=1;i<=m;i++){//种类i的珠子
            if(L[i]==l){//先放等级相同的,因为后面低等级的也会把低等级的放进去
                tot++;//i种珠子被放进孔里
                for(int k=0;k<=sum;k++){//这一步是必要的
                    dp[tot][k]=dp[tot-1][k];
                }
                for(int j=1;j<=p[i];j++){//第i种珠子最多放p[i]个
                    for(int k=j;k<=sum;k++){//判断还够不够放
                        dp[tot][k]=max(dp[tot][k],dp[tot-1][k-j]+w[i][j]);
                    }
                }
            }
        }
    }

    for(int i=0;i<=sum;i++){
        ans=max(ans,dp[tot][i]);
    }
    return ans;

}

int main()
{
    ios::sync_with_stdio(false);
    for(int i=1;i<=6;i++){
        cin>>n[i];
        for(int j=1;j<=n[i];j++){
            int t;
            cin>>t;
            levNum[t]++;
        }
    }
    cin>>m;//一共有m种珠子
    for(int j=1;j<=m;j++){
        cin>>L[j];//第j种珠子的等级
        cin>>p[j];//第j种珠子的上限
        for(int k=1;k<=p[j];k++){
            cin>>w[j][k];
        }
    }

    cout<<DP();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值