洛谷P2383 狗哥玩木棒

题目链接:https://www.luogu.com.cn/problem/P2383

 

这道题是一个搜索题,m<=20,合理的剪枝应该能过

有几个剪枝方法:

    1.将数据从大到小排序在搜索。

    2.如果拼好了就返回。

    3.记录边长度和add,若搜索时又一边超过add/4就返回。

代码:

#include<stdio.h>
int m,n,a[21],add,flag,q;
void px(int k,int s){//排序 
    int i,j,mid,p;
    i=k;j=s;
    mid=a[(k+s)/2];
    do{
        while(a[i]>mid)i++;
        while(a[j]<mid)j--;
        if(i<=j){
            p=a[i];a[i]=a[j];a[j]=p;
            i++;j--;
        }
    }while(i<=j);
    if(k<j)px(k,j);
    if(i<s)px(i,s);
    return;
}
void dfs(int a1,int a2,int a3,int a4,int k){//四条边a1,a2,a3,a4,搜索到第k条木棒
    if(flag)return;//剪枝2
    if(a1>q||a2>q||a3>q||a4>q)return;//剪枝3
    if(k==m+1&&a1==q&&a2==q&&a3==q&&a4==q){flag=1;return;}
    if(k==m+1)return;
    dfs(a1+a[k],a2,a3,a4,k+1);//分别给4条边加木棍长度
    dfs(a1,a2+a[k],a3,a4,k+1);
    dfs(a1,a2,a3+a[k],a4,k+1);
    dfs(a1,a2,a3,a4+a[k],k+1);
    return;
}
int main(){
    scanf("%d",&n);
    for(int h=1;h<=n;h++){
        scanf("%d",&m);
        for(int i=1;i<=m;i++)scanf("%d",a+i);
        add=0;
        for(int i=1;i<=m;i++)add+=a[i];
        q=add/4;
        px(1,m);//排序 剪枝1
        flag=0;
        dfs(0,0,0,0,1);
        if(flag)printf("yes\n");
        else printf("no\n");
    }
    return 0;
}

我可能写的不好,如果有问题,请帮忙指出,谢谢。

posted @ 2020-04-17 21:29  __int128  阅读(143)  评论(0编辑  收藏  举报