洛谷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
原文地址:https://www.cnblogs.com/thmyl/p/7594056.html