递归挺难理解的,我用了最最笨的办法,拿了别人的程序,然后一步一步调试,有点感觉。
有两个回溯,一个是当前的sum超过了average,另一个是拆分当前的已组合的边,因为当前的组合影响了后面的组合。
#include<iostream> using namespace std; #include<iostream> int n,aver,a[22],visited[22],ok; int cmp(const void *p,const void *q) { return *(int *)p-*(int *)q; } void dfs(int sum,int l,int now) { int i; if(ok) return ; if(l==4) { ok=1; return; } if(sum==aver) { dfs(0,l+1,0); return; } for(i=now;i<n;i++) { if(visited[i]) continue; if(sum+a[i]>aver) break; sum+=a[i]; visited[i]=1; dfs(sum,l,i+1); sum-=a[i]; visited[i]=0; } } void d() { int k,total=0,c=0; for(k=0;k<n;k++) total+=a[k]; if(total%4) return ; aver=total/4; for(k=0;k<n;k++) { if(a[k]>aver) return; else if(a[k]==aver) { c++; visited[k]=1; } } if(c==4) { ok=1; return ; } dfs(0,c,0); } int main() { int ca,j,s; scanf("%d",&ca); while(ca--) { scanf("%d",&n); for(j=0;j<n;j++) scanf("%d",a+j); qsort(a,n,sizeof(a[0]),cmp); ok=0; memset(visited,0,sizeof(visited)); d(); if(ok) printf("yes/n"); else printf("no/n"); } return 0; }