• 【DFS】NYOJ-325-zb的生日


    【题目链接:NYOJ-325】

      一道以我名字命名的题目,难道要我生日的时候再A?

      思路:依旧深搜,但这个问题应该有一个专有名词吧,看别的博客说是 “容量为 sum/2 的背包问题”,不懂。。。

     1 // abs()  对应头文件 stdlib.h 返回int参数 
     2 // fabs() 对应头文件 math.h   返回double参数 
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<stdlib.h> 
     6 int W[22],sum,m,n;
     7 void dfs(int cur,int total){
     8     int t =abs(sum - total * 2);
     9     if(t < m) 
    10         m = t;
    11     if(cur == n){
    12 //        int t =abs(sum - total * 2);
    13 //        if(t < m)
    14 //            m = t;
    15         return;//递归边界 
    16     } 
    17     if(total > sum / 2){    //剪枝 
    18 //        int t =abs(sum - total * 2);
    19 //        if(t < m)
    20 //            m = t;
    21         return;
    22     }
    23     dfs(cur + 1,total + W[cur]);    //结点分支。加,右分支 
    24     dfs(cur + 1,total);             //节点分支。不加,左分支 
    25 } 
    26 int main(){    
    27     while(~scanf("%d",&n)){
    28         memset(W,0,sizeof(W));
    29         sum = 0;
    30         m = 10001;
    31         for(int i = 0;i < n;i++){
    32             scanf("%d",&W[i]);
    33             sum += W[i];
    34         }
    35         dfs(0,0);
    36         printf("%d
    ",m);
    37     }
    38     return 0; 
    39 }

      渐渐对搜索有了一些认识,刚开始完全无头绪,要多练习,加油!

      最优解:

        也就是动脑筋剪枝。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int a[25];
     7 int s[25];
     8 int n;
     9 int V;
    10 int ans;
    11 
    12 void DFS(int i,int v)
    13 {
    14     if(i==n+1)
    15     {
    16         ans=max(ans,v);
    17         return;
    18     }
    19     //如果背包已经装满,则不再考虑其他情况。
    20     //如果背包中已有物品加上现有可选物品的总重量都不大于已知的最优解,则剪枝
    21     if(ans==V||v+s[n]-s[i-1]<=ans)
    22         return;
    23     if(a[i]+v<=V)
    24     {
    25         DFS(i+1,v+a[i]);
    26     }
    27     DFS(i+1,v);
    28 }
    29 
    30 int main()
    31 {
    32     while(scanf("%d",&n)==1)
    33     {
    34         s[0]=0;
    35         for(int i=1;i<=n;i++)
    36         {
    37             scanf("%d",&a[i]);
    38             s[i]=s[i-1]+a[i];
    39         }
    40         V=s[n]/2;
    41         ans=0;
    42         DFS(1,0);
    43         ans=s[n]-ans-ans;
    44         printf("%d
    ",ans);
    45     }
    46     return 0;
    47 }

      

  • 相关阅读:
    表格的交集合集等的命令处理
    Linux中screen命令
    Linux中sed基础
    Linux中AWK基础
    聊聊开发中经历的几种后端语言
    C语言NXP S32K144 serial bootloader和C#语言bootloader PC端串口通信程序
    自己用C语言写NXP S32K144 serial bootloader
    C语言NXP S32K116 serial bootloader和C#语言bootloader PC端串口通信程序
    自己用C语言写NXP S32K116 serial bootloader
    C语言RH850 F1L serial bootloader和C#语言bootloader PC端串口通信程序
  • 原文地址:https://www.cnblogs.com/zhengbin/p/4486572.html
Copyright © 2020-2023  润新知