您的位置:首页 > 其它

TOJ 1398 Square --DFS

2010-07-06 18:48 309 查看
给M个小棍(4<=M<=20)问能不能组成正方形框,每个小棍的长度1~10000

此处是在TOJ运行0.00sec的加强版

我一开始的DFS太暴力了。。后来参考别人的日志终于写出了三个参数的DFS~

Submit Time: 2010-07-06 18:21:49
Language: GNU C++ Result: Accepted

Pid: 1398 Time:0.03 sec. Memory:
1204 K.

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int len[20],sum,M;
bool flag,f[20];//flag标记是否找到
bool cmp(int a,int b){return a>b;}
void dfs(int d,int stick,int nowlen){
//i:正在处理的小棍,stick:已经拼好的边框数,nowlen:当前正在拼的框的长度
int j;
if(d>=M||flag||stick>2){
if(stick>2) flag=1;//已经拼好3个框,第四个不用拼了
return ;
}
else {
for(j=d;j<M;j++){
if((!f[j])&&nowlen+len[j]<=sum){
f[j]=1;//标记
if(nowlen+len[j]==sum) dfs(0,stick+1,0);//拼好了一个,继续拼下一个
else dfs(j+1,stick,nowlen+len[j]);//继续拼当前的
f[j]=0;//恢复标记
}
}
}
}
int main(){
int ca,i,j;
scanf("%d",&ca);
while(ca--){
scanf("%d",&M);
for(i=sum=0;i<M;i++){
scanf("%d",&len[i]);
sum+=len[i];
}
if(sum%4!=0) {printf("no\n");continue;}
sum/=4;
sort(len,len+M,cmp);
if(len[0]>sum) {printf("no\n");continue;}
flag=0;
memset(f,0,sizeof(f));
dfs(0,0,0);
printf("%s\n",flag?"yes":"no");
}
//system("pause");
return 0;
}

这个用了0.03秒,思路是用M个小棍拼成4个边框。有几个优化是:

1.所有小棍的和要能够整除4

2.最长的小棍长度不能超过所有小棍和的1/4

3.按小棍的长度从大到小排序,可以很快的排除一些不可能的情况。比如第三个样例有8个小棍1 7 2 6 4 4 3 5,要拼成4个长度为8的框,排序后第一个是7第二个是6,7+6>8,如果较小的数据在前面,比如1 2 3 4在前面,到第四个才发现不行。

4.如果已经拼好了三个边框,那第四个就不需要拼了,剩下的拼成的一定是正方形的第四个边框
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: