题目链接: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; }
我可能写的不好,如果有问题,请帮忙指出,谢谢。
原文:https://www.cnblogs.com/sy666/p/12722601.html