• 洛谷P1441 砝码称重


    P1441 砝码称重

    题目描述

    现有n个砝码,重量分别为a1,a2,a3,……,an,在去掉m个砝码后,问最多能称量出多少不同的重量(不包括0)。

    输入输出格式

    输入格式:

    输入文件weight.in的第1行为有两个整数n和m,用空格分隔

    第2行有n个正整数a1,a2,a3,……,an,表示每个砝码的重量。

    输出格式:

    输出文件weight.out仅包括1个整数,为最多能称量出的重量。

    输入输出样例

    输入样例#1:
    3 1
    1 2 2
    输出样例#1:
    3

    说明

    【样例说明】

    在去掉一个重量为2的砝码后,能称量出1,2,3共3种重量。

    【数据规模】

    对于20%的数据,m=0;

    对于50%的数据,m≤1;

    对于50%的数据,n≤10;

    对于100%的数据,n≤20,m≤4,m<n,ai≤100。

    /*
        看到数据范围那么小,就直接暴力了,但是提高+/省选-的题怎么可能这么好做。。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 25
    using namespace std;
    int a[maxn],b[maxn],c[maxn],n,m,tot,ans,ansnow;
    bool vis[2010];
    void count(int pos,int sum){
        if(!vis[sum]&&sum!=0){
            vis[sum]=1;
            ansnow++;
        }
        if(pos==tot+1)return;
        count(pos+1,sum);
        count(pos+1,sum+c[pos]);
    }
    void dfs(int pos,int cnt){
        if(cnt==m){
            memset(vis,0,sizeof(vis));
            ansnow=0;
            int num=0;
            for(int i=1;i<=n;i++)
                if(b[i]!=-1)c[++num]=b[i];
            count(1,0);
            ans=max(ans,ansnow);
            return;
        }
        if(pos==n+1)return;
        if(n-pos+1<m-cnt)return;
        dfs(pos+1,cnt);//不删掉 
        b[pos]=-1;
        dfs(pos+1,cnt+1);
        b[pos]=a[pos];
    } 
    int main(){
        scanf("%d%d",&n,&m);tot=n-m;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        dfs(1,0);
        cout<<ans;
    }
    60分 暴力TLE
    /*
        直接爆搜删去哪些砝码,统计方案数的时候用一个01背包就可以了
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 25
    using namespace std;
    int a[maxn],b[maxn],c[maxn],n,m,tot,ans,ansnow,f[2010];
    void count(){
        memset(f,0,sizeof(f));
        f[0]=1;
        for(int i=1;i<=n-m;i++)
            for(int j=2000;j>=c[i];j--)
                f[j]+=f[j-c[i]];
        for(int i=1;i<=2000;i++)
            if(f[i])ansnow++;
    }
    void dfs(int pos,int cnt){
        if(cnt==m){
            ansnow=0;
            int num=0;
            for(int i=1;i<=n;i++)
                if(b[i]!=-1)c[++num]=b[i];
            count();
            ans=max(ans,ansnow);
            return;
        }
        if(pos==n+1)return;
        if(n-pos+1<m-cnt)return;
        dfs(pos+1,cnt);//不删掉 
        b[pos]=-1;
        dfs(pos+1,cnt+1);
        b[pos]=a[pos];
    } 
    int main(){
        scanf("%d%d",&n,&m);tot=n-m;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        dfs(1,0);
        cout<<ans;
    }
    100分 搜索+dp
  • 相关阅读:
    Wireshark抓包分析TCP 3次握手、4次挥手过程
    Wireshark基本介绍和学习TCP三次握手
    关于TCP窗口大小
    stat
    Disk
    内存对齐
    Openssl asn1parse命令
    checkinstall
    Nginx
    Linux top
  • 原文地址:https://www.cnblogs.com/thmyl/p/7594056.html
Copyright © 2020-2023  润新知