【转】POJ-2362-Square:简单 DFS+剪枝

思路:

首先将输入的各边长累加求和 即四边形周长sum, 后除4 即边长side,这样 通过DFS 搜索这些sticks能否组合成4根长度均为side 进而确定yes no。

在此 就涉及到搜索顺序了-最优性剪枝: 不难理解 先搜索的小棒子 越长,组合构成side的方式就越少,搜索到结果的时间就越短。

SO从最长的棒子开始进行DFS。

// num表示已确认组合构成 的side的数目 即所求正方形的边数
// len表示所求正方形边长度 s表示搜索起点

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int N, M, sum, side;

bool DFS(int *sticks, bool *visited,\
         int num, int len, int s)
{
    if(num==3)//最优性剪枝 当搜索到3条边都满足时停止搜索
        return true;

    for(int i=s; i>=0; i--)
    {
        if(visited[i])
            continue;

        visited[i]=true;
        if(len+sticks[i]<side)
        {
            if(DFS(sticks,visited,num,len+sticks[i],i))
                return true;
        }
        else if(len+sticks[i]==side)
        {
            if(DFS(sticks,visited,num+1,0,M-1))
                return true;
        }
        visited[i]=false;// 回溯 该边不满足当前side的组合
    }
    return false;
}

int main()
{
    cin>>N;
    while(N--)
    {
        cin>>M;
        sum=0;
        int *sticks=new int[M];
        bool *visited=new bool[M];

        for(int i=0; i<M; i++)
        {
            cin>>sticks[i];
            visited[i]=false;
            sum+=sticks[i];
        }
        sort(sticks,sticks+M);

        side=sum/4;
        if(sum%4!=0||sticks[M-1]>side)//可行性剪枝
        {
            cout<<"no"<<endl;
            continue;
        }
        memset(visited,0,sizeof(visited));
        if(DFS(sticks,visited,0,0,M-1))
            cout<<"yes"<<endl;
        else
            cout<<"no"<<endl;

        delete sticks;
        delete visited;
    }
    return 0;
}

  

posted @ 2015-09-14 19:14  _SunDaSheng  阅读(134)  评论(0编辑  收藏  举报