算法第五章作业

  回溯法,跟dfs差不多,感觉就是dfs的一种具体应用。其实也可以用bfs,但pta上的几道题好像dfs更好用一点。而回溯法的本质就是,走不下去就回头。

  第一题,子集和问题。一开始想着贪心,就给集合排了个序,后来认真读题,发现元素的顺序并不能改变,于是用回溯法找子集。”当问题无解时,输出“No Solution!”。“ 只要在输出之后加一个flag标记一下就好了。在递归的时候如果已经输出就直接return结束程序,如果当前的和已经超过c就结束程序。一开始还是被TLE弄自闭,后来改了几次代码发现,当其他都过了的时候最后一个TLE,当最后一个过了的时候第二第三个样例TLE,于是把两次代码结合一下就过了,还是错了很多次。

void dfs(int num){
    if(flag1){
        return;
    }
    if(sum==c){
        for(int i=1;i<num;i++){
            if(flag[i]){
                cout<<a[i]<<" ";
            }
        }
        flag1=1;
        return;
    }else if(sum>c){
        return;
    }else{
        if(num<=n){
            sum+=a[num];
            flag[num]=1;
            dfs(num+1);
            sum-=a[num];
            flag[num]=0;
            dfs(num+1);
        }
            
    }
    return;
}
第一题代码

  第二题,最佳调度问题。先把时间从大到小排序一遍,然后每一次把时间放在最佳的机器后面,使最长时间不超过标记的时间或者跟标记的时间之间的差是最小的。不断得记录完成任务的最佳的最长时间就可以得出结果。

void dfs(int num,int sum){
    if(num == n+1){
        bestt = min(sum,bestt);
        return ; 
    }else if(sum>bestt){
        return ;
    }else{
        for(int i=1;i<=k;i++){q
            c[i]+=a[num];
            int maxn=0;
            for(int j=1;j<=k;j++){
                maxn=max(maxn,c[j]);
            }
            dfs(num+1,maxn);
            c[i]-=a[num];
        }
    }
}
第二题代码

  第三题,部落卫队问题。一开始的策略是把选的人标记为1,仇人标记为2,用一个数组来存原本的数组以回溯的时候恢复标记,但发现在不断的递归的时候存的数组也在不断得变化导致无法使原本的数组还原。于是就每一次把选的人标记为1,而他的仇人的标记值加2。当还原的时候就把仇人的标记值减二,就能使标记数组复原。

if(vis1[num]==0){
        vis1[num]=1;
        sum++;
    for(int i=1;i<=m;i++){
        if(p[i].mine==num){
            vis1[p[i].enemy]+=2;
        }
        if(p[i].mine>num){
            break;
        }
    }
    dfs(num+1);
    sum--;
    vis1[num]=0;
    for(int i=1;i<=m;i++){
        if(p[i].mine==num){
            vis1[p[i].enemy]-=2;
        }
        if(p[i].mine>num){
            break;
            }
    }
}
dfs(num+1);    
第三题代码

  第四题,最小重量机器设计问题。这题好像没有什么坑,做得挺顺:D  剪枝就是当当前重量超过标记重量或者当前价格超过了最大价格就return

void dfs(int num){
    if(num>n && sumc<=d){
        if(ans>sumw){
            ans = sumw;
            for(int i=1;i<=n;i++){
                sup[i]=vis[i];
            }
        }
        return ;    
    }else{
        if(sumc>d || sumw>ans){
            return ;
        }
        for(int j=1;j<=m;j++){
            sumc+=c[num][j];
            sumw+=w[num][j];
            vis[num]=j;
            if(sumc<=d && sumw<=ans)
                dfs(num+1);
            sumc-=c[num][j];
            sumw-=w[num][j];
            
        }
    }
    return ;
}
第四题代码

 

posted @ 2019-12-06 20:43  jjjjjjjjm  阅读(189)  评论(0编辑  收藏  举报