• 杭电1518 Square(构成正方形) 搜索


    HDOJ1518

    Square

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 11375    Accepted Submission(s): 3660


    Problem Description
    Given a set of sticks of various lengths, is it possible to join them end-to-end to form a square?
     
    Input
    The first line of input contains N, the number of test cases. Each test case begins with an integer 4 <= M <= 20, the number of sticks. M integers follow; each gives the length of a stick - an integer between 1 and 10,000.
     
    Output
    For each case, output a line containing "yes" if is is possible to form a square; otherwise output "no".
     
    Sample Input
    3
    4 1 1 1 1
    5 10 20 30 40 50
    8 1 7 2 6 4 4 3 5
     
    Sample Output
    yes
    no
    yes
     
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1518
     



    题意:m根有长度棍子是否能拼成一个正方形
    利用DFS和剪枝
    在DFS之前首先判断所有棍子的长度之和是否为4的倍数进行一次剪枝,接着用for循环便利一遍,如果棍子的长度大于正方形的边长,则不能构成正方形,进行第二次剪枝。
    在进行一次排序(由于数据较少,可以省略)。
    进行DFS搜索,要标记已经使用了的棍子,一旦不符合要求,就要回溯,并且棍子成为没有使用的状态。
    DFS的时候要注意优化:
      当符合要求的棍子数等于5时,说明已经全部构成正方形的边长,结束。
      每当边长达到要求是,进入下一根棍子DFS搜索。
      还有最重要的一点:每次遍历一边棍子不要从0开始,从上一次搜索状态的下一根棍子开始遍历,否者会超时。
               但是因为数据数目少,我个人感觉也不会要太多时间。可能这用方法是卡着时间过得吧。总之还是自己学的不够好。
     
    至于这一题的部分思路来源于HDOJ1010 Tempter of the Bone
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1010



    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int s[25];
    int sign[25];
    int sum;
    int ave;
    int n;
    int flag;
    void dfs(int t,int len ,int k)
    {
        int i;
        if(t==5)
        {
            flag=1;
            return;
        }
        if(len==ave)
        {
            dfs(t+1,0,0);
            if(flag) return;
        }
        for(i=k; i<n; i++) //从前走到后
            if(sign[i]==0&&s[i]+len<=ave) //标记使用了的棍子
            {
                sign[i]=1;
                dfs(t,s[i]+len,i+1);
                if(flag) return;
                sign[i]=0; //回朔,没有使用状态恢复
            }
            else if(sign[i]==0&&s[i]+len>ave) return;
    }
    int main()
    {
        int i,t;
        scanf("%d",&t);
        while(t--)
        {
            sum=0;
            scanf("%d",&n);
            for(i=0; i<n; i++)
            {
                scanf("%d",&s[i]);
                sum+=s[i];
            }
            if(sum%4!=0)//构边的优化
            {
                cout<<"no"<<endl;
                continue;
            }
            ave=sum/4;
            for(i=0; i<n; i++) //有比边长大的边就不行
                if(s[i]>ave) break;
            if(i<n)
            {
                cout<<"no"<<endl;
                continue;
            }
            memset(sign,0,sizeof(sign));
            sort(s,s+n);
            flag=0;
            dfs(1,0,0);
            if(flag) cout<<"yes"<<endl;
            else cout<<"no"<<endl;
        }
        return 0;
    }
    I am a slow walker,but I never walk backwards.
  • 相关阅读:
    sed 搜索并替换
    error: call of overloaded ‘sqrt(double&)’ is ambiguous
    C++数组读入MATLAB数据
    Ubuntu 18.04 安装 Octave 5.1
    Ubuntu 18.04 安装 CUDA 9.0
    LSTM 神经网络输入输出层
    tf.nn.rnn_cell.MultiRNNCell
    w = tf.Variable(<initial-value>, name=<optional-name>)
    linux下修改环境变量
    linux内核编程学习——草稿
  • 原文地址:https://www.cnblogs.com/GeekZRF/p/4912878.html
Copyright © 2020-2023  润新知