(转自yyr洛谷博客)洛谷 P1441 【砝码称重】

转自yyr博客(https://www.luogu.org/blog/yeyangrui/
(主要是想收录他的)
做这道题之前建议先看一下P2347这一道题,总体思路与这一道题十分相似(这一道题主要是多了一个DFS的过程),下面来说一下这道题(敲黑板):

使用的算法:DFS+DP(看到数据范围这么小应该首先想到的就应该是DFS)

做法:首先通过DFS枚举不取哪M个砝码的情况,再把每种情况依次DP,用一个ma记录最大值(详情见代码部分)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,a[21],f[2001],b[21],last=0,num=0,ma=0;
void search(int k)
{
    if(k==m+1)//当取出了M个砝码时开始计算
    {
        memset(f,0,sizeof(f));//清零!!!这一步不能忘掉
        f[0]=1;//当重量为0时要记为有一种情况,不然结果永远是0
        for(int i=1;i<=n;i++)
        {
            if(b[i]==0)//如果这个砝码没有被拿走
            {
                for(int j=2000;j>=0;j--)//必须倒叙!不然可能f[4]用了4g的砝码,f[8]的时候又把4g的砝码拿出来用一遍
                {
                    if(j+a[i]<=2000&&f[j]!=0)//如果这个重量可以取到且加上新砝码后重量小于等于最大重量(max_n*max_a[I]=2000)
                    {
                        f[j+a[i]]=1;//标记加上砝码后的重量也可以取到
                    }
                }
            }
        }
        num=0;
        for(int i=1;i<=2000;i++)//看哪些重量可以取到
            if(f[i])
                num++;
        if(num>ma)//记录最大值
            ma=num;
        return;
    }
    for(int i=last+1;i<=n;i++)//枚举取砝码的情况(这里采用的是顺次枚举,减少耗时)
    {
        b[i]=1;//记录为取过了
        last=i;//记录取到哪一个了
        search(k+1);//接着往下取
        b[i]=0;//回溯
    }
}
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];//读入
    search(1);//枚举每种情况
    cout<<ma;
    return 0;
} 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,776评论 0 33
  • 渐渐的 我的注意力被下面这块大地分散 我开始同伙伴们走散 忘记了南方的归途 我顺着他们的气息找寻 只有一片深邃的蓝...
    Maymae阅读 275评论 1 2
  • 今天看到一道前端js面试题,加深了我对数组的一些理解。 var arr1 = 'edison'.split('')...
    edisonchan阅读 783评论 0 0
  • 今天忽然在想,要不要为了合群而改变自己的性格,压低自己的气质和修养? 不过有时候,环境可以改变一个人,就算不想改变...
    潜力股丶阅读 201评论 0 0