#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sticks[20];
bool visit[20];
int cmp(const void * a,const void *b)
{
return *(int *)b - *(int *)a;
}
bool dfs(int s,int N,int cur,int left,int num,int lengthside) // num 是已经拼好的 长度
{ //s 是搜索木棍的起始位置 N 是木棍的总数 left是要拼凑的长度 cur是当前的长度
if (num==3) //找到三根 其他的就不用找了
return true;
int i;
for (i=s;i<N;i++)
{
if (!visit[i])
{
if (cur + sticks[i] == lengthside) // 刚好拼完一根
{
visit[i] = true;
if (dfs(0,N,0,lengthside,num+1,lengthside))
return true;
visit[i] = false;
}
else if (cur + sticks[i] < lengthside)
{
visit[i] = true;
if (dfs(i+1,N,cur+sticks[i],left - sticks[i],num,lengthside))
return true;
visit[i] = false;
}
}
}
return false;
}
int main()
{
int test,N,i,sum,max,lengthside;
scanf("%d",&test);
while(test--)
{
scanf("%d",&N);
sum = 0;
max = 0;
for (i=0;i<N;i++)
{
scanf("%d",&sticks[i]);
sum += sticks[i];
if (max < sticks[i])
max = sticks[i];
}
if ( sum % 4 != 0 || sum / max <4) //基本剪枝
{
printf("no\n");
continue;
}
memset(visit,false,sizeof(visit));
qsort(sticks,N,sizeof(int),cmp);
lengthside = sum / 4;
if (dfs(0,N,0,lengthside,0,lengthside))
printf("yes\n");
else
printf("no\n");
}
return 0;
}
两题基本一样
先对木棍排序 ,然后按照质指定的长度在数组里搜索。
刚开始,这两题都是按照子集和的方法做的,一直TLE,无论怎么剪枝都不行,后来一想,还是按照指定长度搜索正解效率更高。