贪吃的大嘴 多重背包 dp

7-4 贪吃的大嘴 (15分)
有一只特别贪吃的大嘴,她很喜欢吃一种小蛋糕,而每一个小蛋糕有一个美味度,而大嘴是很傲娇的,一定要吃美味度和刚好为m的小蛋糕,而且大嘴还特别懒,她希望通过吃数量最少的小蛋糕达到这个目的.所以她希望你能设计一个程序帮她决定要吃哪些小蛋糕.

输入格式:
先输入一行包含2个整数m、n,表示大嘴需要吃美味度和为m的小蛋糕,而小蛋糕一共有n种,下面输入n行,每行2个整数,第一个表示该种小蛋糕的美味度,第二个表示蛋糕店中该种小蛋糕的总数

输出格式:
输出一行包含一个整数表示大嘴最少需要吃的小蛋糕数量,若大嘴无法通过吃小蛋糕达到m的美味度和,则输出"><“.

输入样例:
在这里给出一组输入。例如:

10 2
4 1
2 10
输出样例:
在这里给出相应的输出。例如:

4
输入样例:
在这里给出一组输入。例如:

10 2
4 1
7 3
输出样例:
在这里给出相应的输出。例如:

<

题解:这是一个多重背包的问题。
两种解法
第一种
用dp代表,美味度为i时吃的最少的蛋糕块数量。
那么他的转移方程为 dp[k]=min(dp[k],dp[k-v[i]]+1);
一共有三重循环,分别代表蛋糕的种类数,每种蛋糕的数量以及对应的美味度时吃的最少的蛋糕数。
代码如下:

#include <bits/stdc++.h>
#include <algorithm>
#include<iostream>
#include <stdio.h>
#define INF 0x3f3f3f3f
const int maxn=500005;
using namespace std;
typedef long long ll;
int dp[maxn];
int a[maxn];
int v[maxn];
int main(){
    
    
    int m,n,t,va;
    cin>>m>>n;
    memset(dp,INF,sizeof(dp));
    for(int i=1;i<=n;i++){
    
    
        cin>>va>>t;
        //dp[va]=1;
    /*
        for(int k=1;k<=t;k++){
            a[s+k]=v;
        }
        s+=t;*/
        v[i]=va;
        a[i]=t;
    }
    //cout<<s<<endl;;
    dp[0]=0;
    for(int i=1;i<=n;i++){
    
    
        for(int j=1;j<=a[i];j++){
    
    
            for(int k=m;k>=v[i];k--){
    
    
               if(k-v[i]>=0){
    
    
                    //dp[i-a[j]*k]=k;
                    dp[k]=min(dp[k],dp[k-v[i]]+1);
                }
                //if(k-a[i]==0)
                   //f=1;
                //cout<<"i="<<k<<"dp[i]="<<dp[k]<<endl;
            }
        }
    }
    if(dp[m]!=INF)
        cout<<dp[m]<<endl;
    else
        cout<<"><"<<endl;
    return 0;
}

第二种方法:把这个多重背包转为为一个普通的0-1背包,多重背包是同一类有多个,那么只需要把同类的蛋糕一个个单独拿出来,此时的模型就变成了一个最简单的0-1背包。
代码

#include <bits/stdc++.h>
#include <algorithm>
#include<iostream>
#include <stdio.h>
#define INF 0x3f3f3f3f
const int maxn=500005;
using namespace std;
typedef long long ll;
int dp[maxn];
int a[maxn];
int v[maxn];
int main(){
    
    
    int m,n,t,va;
    cin>>m>>n;
    memset(dp,INF,sizeof(dp));
    int s=0;
    for(int i=1;i<=n;i++){
    
    
        cin>>va>>t;
        //dp[va]=1;
        for(int k=1;k<=t;k++){
    
    
            a[s+k]=va;
        }
        s+=t;
    }
    //cout<<s<<endl;
    dp[0]=0;
    for(int i=1;i<=s;i++){
    
    
        for(int j=m;j>=a[i];j--){
    
    
            dp[j]=min(dp[j],dp[j-a[i]]+1);

        }
    }
    if(dp[m]!=INF)
        cout<<dp[m]<<endl;
    else
        cout<<"><"<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/u011612364/article/details/108908591