zoukankan      html  css  js  c++  java
  • DFS HDU 1518 Square

    因为n<=20,较小,用DFS,但是要剪枝,不然就TLE

    这个题是校队讨论时ZZM说的,然后里面有讲到一种错误的思路,用0-1背包恰好背满边长,边长的2倍 ,边长的三倍,边长的四倍

    事实上,如果数据是7 7 2 1 7 8就是一个反例,每种都能背满,但是无法构成四边形。

    然后我自己先写了一个DFS,用四个数d1,d2,d3,d4来存状态,对于每根棍子,有四种可能,分别是放d1,d2,d3,d4里,再往里搜,回退的时候,d1,d2,d3,d4回到原来的状态。

    一个剪枝是当d1,d2,d3,d4中出现大于边长的值就return,不往下搜了。

    还有就是已经搜到可行解了,也不搜了。

    这样最坏情况下复杂度为O(4^n).很高,一直T,剪枝也不行,我认为我自己的DFS可能很搓,因为貌似复杂度被乘了一个4!,对于这四个数有一个全排列的重复。

    不过胜在想法自然。

    接着我就百度了别人的代码,大概就是令设一个数组b[],用来记录哪条边被用过了,然后用没有用过的边去构造一条值为正方形边长的边。

    DFS中的第一个参数是从哪个点开始找,边的长度< 边长时,按顺序往后搜,别再从0开始搜了``

    还有就是找到三条边就够了,剩下的一条边就用剩下的棍子拼就行。

    真的感觉自己对DFS理解还是不够深刻,得努力

    贴代码:

    View Code
     1 #include <cstdio>
     2 #include <cstring>
     3 bool flag;
     4 int p[22];
     5 int n;
     6 int bc;//边长
     7 bool b[22];
     8 void dfs(int x,int len,int cnt)
     9 {
    10     if(cnt == 3)
    11     {
    12         flag= true;
    13         return;
    14     }
    15     if(flag)
    16         return;
    17     for(int i= x; i<n; ++i)
    18     {
    19         if(!b[i] && len+p[i] <= bc)
    20         {
    21             b[i] = 1;
    22             if( len+p[i] == bc)
    23                 dfs(0,0,cnt+1);
    24             else
    25                 dfs(i+1,len+p[i],cnt);
    26             b[i] = 0;
    27         }
    28     }
    29 }
    30 int main()
    31 {
    32 //    freopen("in.cpp","r",stdin);
    33     int T;
    34     scanf("%d",&T);
    35     while(T--)
    36     {
    37         scanf("%d",&n);
    38         int sum = 0;
    39         for(int i=0; i<n; ++i)
    40         {
    41             scanf("%d",&p[i]);
    42             sum += p[i];
    43         }
    44         if(sum != sum/4*4)
    45         {
    46             printf("no\n");
    47             continue;
    48         }
    49         bc = sum/4;
    50         flag = false;
    51         memset(b,false,sizeof(b));
    52         dfs(0,0,0);
    53         if(flag)
    54             printf("yes\n");
    55         else
    56             printf("no\n");
    57     }
    58     return 0;
    59 }
  • 相关阅读:
    tera term通过ttl脚本 自动连接服务器
    shell脚本生成xml文件
    MarkDown语法练习笔记
    linux nkf 日文编码转换命令[转载]
    Shell脚本传递带有空格的参数[摘录自网络]
    JavaScript思维导图—函数基础
    JavaScript思维导图—运算符
    JavaScript思维导图—数组
    JavaScript思维导图—流程控制
    JavaScript思维导图—正则表达式
  • 原文地址:https://www.cnblogs.com/allh123/p/3043165.html
Copyright © 2011-2022 走看看