DP-背包问题的一些题目

1.金明的预算方案(分组背包)

487. 金明的预算方案 - AcWing题库

解题

对于每组主件和附件,我们对它们不同的选择方式构成分组背包的一组。比如说某组存在一个主件和一个附件,那么把它转化为分组背包问题,这一组中的元素有①选择主件不选择附件②选择主件和附件③都不选择。

在枚举每一组中的不同元素时,可以采取二进制的方法。

二维代码:

#include
#include
using namespace std;
const int N=32010,M=65;
typedef pair PII;
#define x first
#define y second
int n,m;
PII zhujian[M];
vector fujian[M];
int f[M][N];
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
    {
        int vv,pp,qq;
        scanf("%d%d%d",&vv,&pp,&qq);
        if(qq==0) zhujian[i]={vv,pp*vv};
        else fujian[qq].push_back({vv,pp*vv});
    }
    for(int i=1;i<=n;i++)
    {
        if(zhujian[i].x)
            for(int j=0;j<=m;j++)
            {
                int t=fujian[i].size();
                f[i][j]=f[i-1][j];
                for(int k=0;k<1<>u&1)
                        {
                            v+=fujian[i][u].x;
                            w+=fujian[i][u].y;
                        }
                    }
                    if(j>=v) f[i][j]=max(f[i][j],f[i-1][j-v]+w);
                }
            }
        else
            for(int j=0;j<=m;j++)
                f[i][j]=f[i-1][j];
    }
    printf("%d",f[n][m]);
}

一维代码:

#include
#include
using namespace std;
const int N=32010,M=65;
typedef pair PII;
#define x first
#define y second
int n,m;
PII zhujian[M];
vector fujian[M];
int f[N];
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
    {
        int vv,pp,qq;
        scanf("%d%d%d",&vv,&pp,&qq);
        if(qq==0) zhujian[i]={vv,pp*vv};
        else fujian[qq].push_back({vv,pp*vv});
    }
    for(int i=1;i<=n;i++)
    {
        if(zhujian[i].x)
            for(int j=m;j>=0;j--)
            {
                int t=fujian[i].size();
                for(int k=0;k<1<>u&1)
                        {
                            v+=fujian[i][u].x;
                            w+=fujian[i][u].y;
                        }
                    }
                    if(j>=v) f[j]=max(f[j],f[j-v]+w);
                }
            }
    }
    printf("%d",f[m]);
}

2.货币系统NOIP2018(完全背包)

532. 货币系统 - AcWing题库

解题

这道题有一个性质,b是a的子集,因为如果bn不属于a,由于a和b是等价的,则就可以用任意的a表示出bn,也就可以用任意的b表示出bn,此时的bn就没必要存在在b中了。

因此,我们只需要对a中的元素进行决策,决策的依据是当前元素是否能被a中的其他元素凑出,如果能被凑出,则当前元素无效,不能被凑出则有效。

判断元素能否被凑出,等效于判断当有n个可以无限次选择的元素时,当前元素是否能被凑出,其实就是一个完全背包的操作

#include
#include
#include
using namespace std;
const int N=25010;
int T;
int f[N];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
       
        int a[N];
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        sort(a+1,a+1+n);

        memset(f,0,sizeof(f));
        f[0]=1;
        int cnt=0;
        
        for(int i=1;i<=n;i++)
        {
            if(f[a[i]]==0) cnt++;
            for(int j=a[i];j<=a[n];j++)
            {
                f[j]+=f[j-a[i]];
            }
        }
        printf("%d\n",cnt);
    }
}

你可能感兴趣的:(动态规划,动态规划,算法,c++)