C++题解 P5823 4.三角形(triangle)
原题: 5823.4.三角形(triangle)2023zjhs020 于2025-05-22
这是一道深搜,暴搜有20分。(2022年绍兴小学组的压轴题,总得有点货)
但只要你想得到思路,再垃圾的深搜,也能过这道题。
因为,n<=5,就算你没有任何减枝。也不会炸。
就比如果这个代码,因为它的时间复杂度是O(n!)
但也是只有到O(16!),才会炸掉。
代码的思路也是很纯粹,原来暴搜是挑选第一条边时,是会每个都试一遍,所以才会TLE。而深搜呢?再选第一条边时,就会用到记忆化。选过的就不要了。这样就炸不掉了。
最后,还有一个条件,就是组成三角形时,也要判断一下三条边是否能组成三角形,而不是啥都能凑。1+2>3&&1+3>2&&2+3>1.
#include<bits/stdc++.h>//头文件
using namespace std;
long long n,s[20],ans=0;//定义
long long b[20]={0};//记忆化,没用过为0,用过为1,可调换
void dfs(int x)//深搜,x表示三角形的第一条边
{
if(x==n+1) {//全部都可以,因为第一:三条边找到了,全部记忆化后,碰到下面那个就会下去搜,第二:n<=5,炸不掉,(这里其实还可以改,有兴趣的可以自己动手改一下)
ans++;//找到一个,方案增加
return ;//返回找
}
if(b[x])//如果已经用过了
{
dfs(x+1);//下去搜
return ; //这里要有返回,不然等这回溯回来时会再去下面的循环
}
for(int y=x+1;y<=n;y++)//两层循环,第一层,找三角形的第二条边,
{
if(!b[y])//用过吗,没用过继续
{
for(int z=y+1;z<=n;z++)//再来一个,三角形的第三条
{
if(!b[z])//用过吗?,没用过继续
{
if(s[x]+s[y]>s[z]&&s[x]+s[z]>s[y]&&s[y]+s[z]>s[x])//判断是否能组成,符合条件
{
b[x]=b[y]=b[z]=1;//用过了
dfs(x+1);//继续搜
b[x]=b[y]=b[z]=0;//回溯回来时得取消,不然就搜不下去了
}
}
}
}
}
}
int main()//主函数
{
//freopen("triangle.in","r",stdin);
// freopen("triangle.out","w",stdout);
cin>>n;//输入
n*=3;//要乘3
for(int i=1;i<=n;i++) cin>>s[i];//循环输入
sort(s+1,s+1+n);//最好来个排序,更好
dfs(1);//从第一条边开始
cout<<ans;//输出方案数,(不懂得去推一下搜的过程,再看)
return 0;//结束
}