题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1518
在无数wrong answer 和tle 以后终于过了。
需要注意以下几点:
1、在寻找sum/4的组合的时候,当前满足条件的组合,不一定是最终的组合。
所以:
vis[i] = 1;//标记。
dfs();
vis[i]=0;//撤除标记,寻找是否有新的满足条件的组合。
作为思路不清的菜鸟,我犯了这个毛病。
2、在寻找其中一个满足条件的组合的时候,我们可以有序的,从第一个没有别访问过的数开始,然后到了下一个DFS的时候挨个向后找。
而不是每个DFS都把所有的每访问过的数,枚举一遍,否则会超时。
代码应该是:
void dfs(int edge,int l,int k)
{
int i;
if(edge==5)
{
flag=1;
return;
}
else
{
for(i=k;i<n;i++)
{
if(!vis[i] && l+a[i] <=sum)
{
if(l+a[i]==sum)
{
vis[i]=1;
dfs(edge+1,0,0);
if(flag)
return;
vis[i]=0;
}
else if(l+a[i]<sum)
{
vis[i] = 1;
dfs(edge,a[i]+l,i+1);
if(flag)
return;
vis[i]=0;
}
}
}
}
}
而不是:
void dfs(int edge,int l)
{
int i;
if(edge==5)
{
flag=1;
return;
}
else
{
for(i=0;i<n;i++)
{
if(!vis[i] && l+a[i] <=sum)
{
if(l+a[i]==sum)
{
vis[i]=1;
dfs(edge+1,0);
if(flag)
return;
vis[i]=0;
}
else if(l+a[i]<sum)
{
vis[i] = 1;
dfs(edge,a[i]+l);
if(flag)
return;
vis[i]=0;
}
}
}
}
}
以上就是我的错误,希望别的同学可以有则改之,无则加勉。
完整的AC代码如下:
#include<stdio.h>
#include<string.h>
int n,sum,l;
int a[30],vis[30];
int flag;
void dfs(int edge,int l,int k)
{
int i;
if(edge==5)
{
flag=1;
return;
}
else
{
for(i=k;i<n;i++)
{
if(!vis[i] && l+a[i] <=sum)
{
if(l+a[i]==sum)
{
vis[i]=1;
dfs(edge+1,0,0);
if(flag)
return;
vis[i]=0;
}
else if(l+a[i]<sum)
{
vis[i] = 1;
dfs(edge,a[i]+l,i+1);
if(flag)
return;
vis[i]=0;
}
}
}
}
}
int main()
{
int t,i;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
sum=0;
int Max=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
sum+=a[i];
if(Max<a[i])
Max=a[i];
}
if(sum%4!=0)
{
printf("no\n");
continue;
}
sum=sum/4;
if(sum<Max)
{
printf("no\n");
}
flag=0;
memset(vis,0,sizeof(vis));
dfs(1,0,0);
if(flag)
printf("yes\n");
else
printf("no\n");
}
return 0;
}