POJ 2362 Square 经典DFS回溯

来源:互联网 发布:除了在淘宝开店 编辑:程序博客网 时间:2024/06/04 19:57

http://poj.org/problem?id=2362


题目大意:

给出一些木棍的长度,判断能否围成正方形。


解题思路:

主要思想就是利用DFS和回溯,不断的判断是否能组成4条相同长度的边。

这道题是一道非常经典的回溯问题,对我来说也有很大的启发作用。首先对递归的理解更深刻了,同时也了解了回溯

的一般写法,并且也算是第一次接触了剪枝吧。

先说下递归吧,把递归看做是在一个栈中的就很好理解了,调用的过程是不断入栈的过程,函数返回就是不断出栈的过程,回溯其实就是在函数返回的过程中对调用函数时一些标志变量的改变,如visit数组。剪枝的目的是节省时间,由于递归在数据量较大时消耗时间大,所以函数调用过程中要有选择的进行递归调用,这也就是所谓的剪枝,剪枝的写法要分析具体的问题,例如这道题中,所以边的长度加起来要能被4整除,在这基础上只要找到3条边就可以进行判断了,这些也都算是小小的剪枝吧。



<span style="font-size:18px;">#include<iostream>#include<algorithm>#include<string>#include<cstring>using namespace std;int visit[30];int n,aver;int a[30];int dfs(int cur,int start,int counter){    if(cur==aver)    {        cur=0;        start=0;        counter++;        if(counter==3)        {            return 1;        }    }    for(int i=start;i<n;i++)    {        if(visit[i])            continue;        if(a[i]+cur>aver)            continue;        visit[i]=1;        if(dfs(cur+a[i],i+1,counter))            return 1;        visit[i]=0;      //回溯    }    return 0;}bool cmp(int a,int b){    return  a>b;}int main(){    int t,sum;    cin>>t;    while(t--)    {        memset(visit,0,sizeof(visit));        cin>>n;        sum=0;        for(int i=0;i<n;i++)        {            cin>>a[i];            sum+=a[i];        }        if(sum%4!=0)        {            cout<<"no"<<endl;            continue;        }        sort(a,a+n,cmp);        //由大到小排序        aver=sum/4;        if(dfs(0,0,0))            cout<<"yes"<<endl;        else            cout<<"no"<<endl;    }    return 0;}</span>


0 0
原创粉丝点击