您的位置:首页 > 其它

【DFS&&搜索剪枝】CODE[VS] 3498 小木棍

2016-11-10 11:31 561 查看
点击进入地狱

这个搜索做得比较早了….

11.1下午来机房开始搞这个暴搜,结果一直TLE&&WA



后来放了会没再管,11.3号早上又想了起来

然后就开始了悲惨的WA之路QAQ:





题是好题,是我太弱了…..

这道题的思路:

暴力枚举

我们枚举目标长度,当目标长度可以整除给出木棍长度之和的时候,我们再去判断这些木棍是否可以拼成该长度,这比枚举木棍根数要快并且更容易想到优化

(别问我怎么知道的,说多了都是泪)

但是裸暴力会超时,所以需要剪枝优化

1.首先很显然的一个剪枝,就是贪心,先将木棍从长到短排序,然后拼的时候先枚举长木棍的组合,因为长木棍限制更高,能够很快排除不少情况

2.然后我们可以在枚举目标木棍长度的时候,从给出木棍最长的开始到所有长度总和结束,因为显然目标木棍长度必然大于或等于数据给出的最长木棍长度

3.如果当前长度为0(第一层搜索),完成之后直接返回

4.在拼接木棍的的时候,相同长度的木棍之前用过,记录一下,下次直接continue

5…………………………………………………………………………………………..

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>

using namespace std;

int n,u;
int osu;
int len[105];
int totlen;
int ans = 0x3ffffff;
bool used[105];

inline int read()
{
char ch;
int f = 1;
int data = 0;
while(ch < '0'||ch > '9')
{
ch = getchar();
if(ch == '-')
f = -1;
}
do{
data = data*10+ch-'0';
ch = getchar();
}while(ch <= '9'&&ch >= '0');

return f*data;
}

bool cmp(const int a,const int b) { return a > b;}

inline bool dfs(int s,int nowlen,int viv)
{
bool bj;
if(nowlen == 0) bj = true;
else bj = false;
if(s == u) return true;
for(int i = viv;i <= n;i++)
{
if(used[i] == 1) continue;
if(nowlen + len[i] == osu)
{
used[i] = 1;
if(dfs(s+1,0,0)) return true;
used[i] = 0;
return false;
}
else if(nowlen + len[i] < osu)
{
used[i] = 1;
if(dfs(s,nowlen+len[i],i)) return true;
used[i] = 0;
if(bj == true) return false;
}
}
return false;
}

int main()
{
n = read();
for(int i = 1;i <= n;i++)
{
len[i] = read();
totlen += len[i];
}
sort(len+1,len+1+n,cmp);
for(int i = len[1];i <= totlen;i++)
{
if(totlen%i == 0)
{
osu = i;
u = totlen/i;
memset(used,0,sizeof(used));
if(dfs(1,0,0)) { ans = min(ans,i); continue;}
}
}
printf("%d\n",min(ans,totlen));

return 0;
}


THE END

By Peacefuldoge

http://blog.csdn.net/loi_peacefuldog
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dfs 搜索