此做法能过的原理是?
查看原帖
此做法能过的原理是?
38035
Uni_Tune楼主2024/4/1 23:36
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> check;
int n,m,mid,dans;
long long ans[31],a[31];
/*void dfs(int x,int tot,int now){
    if(tot>m||now>dans||(check.count(tot)&&check[tot]<now)) return;
    if((long long)((long long)tot+(ans[n]-ans[x-1]))*2<m) return;
    if(tot==m){
        dans=min(dans,now);
        return;
    }
    if(x==mid+1){
        if(check.count(tot)) check[tot]=min(check[tot],now);
        else check[tot]=now;
        return;
    }
    dfs(x+1,tot,now);
    dfs(x+1,tot+(a[x]<<1),now);
    dfs(x+1,tot+a[x],now+1);
    return;
}
void dfs1(int x,int tot,int now){
    if(tot>m||now>dans||(check.count(m-tot)&&check[m-tot]+now<dans)) return;
    if(ans[mid]*2+(long long)tot+(ans[n]-ans[x-1])*2<m) return;
    if(tot==m){
       dans=min(dans,now);
       return;
    }
    if(x==n+1){
        if(tot<=m&&check.count(m-tot)) dans=min(dans,now+check[m-tot]);
        return;
    }
    dfs1(x+1,tot,now);
    dfs1(x+1,tot+(a[x]<<1),now);
    dfs1(x+1,tot+a[x],now+1);
    return;
}
int main(){
    scanf("%d%d",&n,&m);
    m<<=1;
    dans=n+2;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) ans[i]=ans[i-1]+a[i];
    mid=n/2;
    dfs(1,0,0);
    dfs1(mid+1,0,0);
    if(dans>n) printf("-1");
    else printf("%d",dans);
    return 0;
}*/
long long min(long long a, long long b) {
    return a > b ? b : a;
}
int compare(const void* a, const void* b) {
    return (*(long long*)b - *(long long*)a);
}
bool comp(long long x,long long y){
    return x<y;
}
void dfs(int x,long long tot,int now){
    if(now>=dans) return;
    if(tot==m){
        dans=min(now,dans);
        return;
    }
    if(tot>m||tot+(ans[n]-ans[x-1])*2<m||x>n) return;
    dfs(x+1,tot,now);
    dfs(x+1,tot+a[x]*2,now);
    dfs(x+1,tot+a[x],now+1);
}
int main(){
    ios::sync_with_stdio(NULL);
    cin.tie(NULL);
    cin>>n>>m;
    m*=2;
    dans=n+2;
    for(int i=1;i<=n;i++) cin>>a[i];
    //sort(a+1,a+n+1);
    qsort(a+1,n,sizeof(long long),compare);
    for(int i=1;i<=n;i++) ans[i]=ans[i-1]+a[i];
    dfs(1,0,0);
    if(dans>n) cout<<-1;
    else cout<<dans;
    return 0;
}

此问题的起因是我的折半搜索做法在洛谷能过但是在蓝桥杯官方提交处T了最后三个点(?

然后我打开那边的题解区学习智慧,发现不少题解看似并没有折半搜索但是能过,我试着在两边交了一下甚至每个点都不超过10ms(??

代码如上,就是把我初始化的sort改成了qsort然后就过了?然后就不太清楚这里为什么这么改就能过,是否有什么神秘智慧还是我读错了

2024/4/1 23:36
加载中...