关于组合型枚举的顺序选择问题
  • 板块学术版
  • 楼主_lwt
  • 当前回复1
  • 已保存回复1
  • 发布时间2021/4/23 20:14
  • 上次更新2023/11/5 00:12:32
查看原帖
关于组合型枚举的顺序选择问题
363441
_lwt楼主2021/4/23 20:14

在组合型枚举中,两种枚举方式有什么区别?

方式1:按照指数型枚举进行,枚举每个数选或不选,再加上可行性剪枝

方式2:枚举每个位置可以填什么数,用一个变量标记下一个要选择的数的下标,避免重复枚举

方式1,2在时间效率上有什么区别?

分别在什么情况下使用?

为什么“小猫爬山”使用方式1可以通过,而方式2会超时?

求解答

小猫爬山1:可以通过

#include<iostream>
#include<algorithm>
#define N 20 
using namespace std;
int a[N],v[N],n,m,ans=N;
void dfs(int cat,int car){
    if(car>=ans) return ;//剪枝
    if(cat==n+1) {//n操作结束,到n+1截止 
        ans=car;
        return ;
    }
    for(int i=1;i<=car;i++){//从1开始而不是从0开始是因为1缆车才开始放入小猫,直到第car个缆车 
        if(a[cat]+v[i]<=m){
            v[i]+=a[cat];
            dfs(cat+1,car);
            v[i]-=a[cat];
        }
    }
    v[car+1]=a[cat];
    dfs(cat+1,car+1);
    v[car+1]=0; 
}
int main(){
    cin >> n >> m;
    for(int i=1;i<=n;i++) cin >> a[i];
    sort(a+1,a+n+1);
    reverse(a+1,a+n+1);//剪枝 
    dfs(1,0); //当前为第1只猫,当前为第0辆车(在dfs中直接新建缆车)
    cout << ans << endl; 
    return 0;
} 
小猫爬山,方式2,超时

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=25;
int n,m,a[N],cnt[N],car=1,start=1,ans=0x7fffffff,b[N];
void dfs(int c,int s,int cat){
    if(c>=ans) return ;
    if(cat>n) {
        ans=min(ans,c);
        return ;
    }
    int flag=1;
    for(int i=s;i<=n;i++){
        if(cnt[c]+a[i]<=m&&b[i]==0){
            b[i]=1;
            cnt[c]+=a[i];
            dfs(c,s+1,cat+1);
            b[i]=0;
            cnt[c]-=a[i];
            flag=0;
        }
    }
    if(flag){
        dfs(c+1,1,cat);
    }

    return ;
}
int main(){
    cin >> n >> m;
    for(int i=1;i<=n;i++){
        cin >> a[i];
    }
    sort(a+1,a+n+1);
    reverse(a+1,a+n+1);
    dfs(car,start,1);
    cout << ans << endl;
    return 0;
}
2021/4/23 20:14
加载中...