P1441 砝码称重 DFS回溯+DP

题目描述

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

请注意,砝码只能放在其中一边。

输入输出格式

输入格式:

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

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

输出格式:

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

扫描二维码关注公众号,回复: 5946040 查看本文章

输入输出样例

输入样例#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。

一开始总想着骚操作  但是细节太多处理不了

直接暴力搜索就能过的。。。。

没任何优化  1600ms

#include<bits/stdc++.h>
using namespace std;
//input b y bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
#define inf 0x3f3f3f3f
//////////////////////////////////
#define N  20+9

int n,m;
int vis[N];
int a[N];
int q[N];
int dp[2010];
int cnt;
int maxx;

void dp1()
{
    CLR(dp,0);
    dp[0]=1;
    int cnt=0;
    rep(i,1,n)
    if(vis[i])
    {
        repp(j,2000,0)
        if(dp[j]&&!dp[j+a[i]])dp[j+a[i]]=1,cnt++;
    }
    maxx=max(maxx,cnt);
}


void dfs(int cur,int num)
{
    if(num>n-m)return ;
    if(num==n-m)
    {
     dp1();
     return ;
    }
    rep(i,cur,n)
    if(!vis[i])
    {
        vis[i]=1;
        dfs(i+1,num+1);
        vis[i]=0;
    }
    return ;
}


int main()
{
    RII(n,m);
    rep(i,1,n)
    RI(a[i]);
    
    maxx=0;
    dfs(1,0);
    cout<<maxx;
    return 0;
}
View Code

加一个dp上界的优化   950ms

#include<bits/stdc++.h>
using namespace std;
//input b y bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
#define inf 0x3f3f3f3f
//////////////////////////////////
#define N  20+9

int n,m;
int vis2[200];
int vis[N];
int a[N];
int q[N];
int dp[2010];
int cnt;
int tot;
int maxx;

void dp1()
{
    CLR(dp,0);
    dp[0]=1;
    int cnt=0;
    rep(i,1,n)
    if(vis[i])
    {
        repp(j,tot,0)
        if(dp[j]&&!dp[j+a[i]])dp[j+a[i]]=1,cnt++;
    }
    maxx=max(maxx,cnt);
}

void dfs(int cur,int num)
{
    if(num>n-m)return ;
    if(num==n-m)
    {
     dp1();
     return ;
    }
    rep(i,cur,n)
    if(!vis[i])
    {
        vis[i]=1;
        dfs(i+1,num+1);
        vis[i]=0;
    }
    return ;
}

int main()
{
    RII(n,m);
    tot=0;
    rep(i,1,n)
    RI(a[i]),tot+=a[i];

    maxx=0;
    dfs(1,0);
    cout<<maxx;
    return 0;
}
View Code

再次上界优化  400ms!!!!

#include<bits/stdc++.h>
using namespace std;
//input b y bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
#define inf 0x3f3f3f3f
//////////////////////////////////
#define N  20+9
int n,m;
int vis[N];
int a[N];
int dp[2010];
int cnt;
int maxx;

void dp1()
{
    CLR(dp,0);
    dp[0]=1;
    int cnt=0;
    int tot=0;
    rep(i,1,n)
    if(vis[i])
    {
        repp(j,tot,0)
        if(dp[j]&&!dp[j+a[i]])dp[j+a[i]]=1,cnt++;
        tot+=a[i];
    }
        maxx=max(maxx,cnt);
}

void dfs(int cur,int num)
{
    if(num>n-m)return ;
    if(num==n-m)
    {
     dp1();
     return ;
    }
    rep(i,cur,n)
    if(!vis[i])
    {
        vis[i]=1;
        dfs(i+1,num+1);
        vis[i]=0;
    }
    return ;
}

int main()
{
    RII(n,m);
    rep(i,1,n)
    RI(a[i]);

    maxx=0;
    dfs(1,0);
    cout<<maxx;
    return 0;
}
View Code

  

猜你喜欢

转载自www.cnblogs.com/bxd123/p/10736650.html
今日推荐