题目在蓝桥云课上:
1.四位密码锁
四层,每层遍历所有可能的数字。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int sum=0;
void dfs(int depth,int ans)
{if(depth==4) //不再递归 {if(ans==384) {sum++;}return;}for(int i=1;i<=9;i++){ans*=i; dfs(depth+1,ans);ans/=i; }
}int main()
{dfs(0,1); cout<<sum<<endl;return 0;
}
2.素数环
首尾之和满足素数,每往下层遍历一次,即pre变next,每层遍历所有可能
#include<bits/stdc++.h>
using namespace std;
int n,sum=0,visit[21]= {0};
vector<int>q;
int fun(int x)
{if(x<=1){return 0;}for(int i=2; i<=sqrt(x); i++){if(x%i==0){return 0;}}return 1;
}void dfs(int cur,int pre)
{if(cur==n){if(fun(pre+1)) //首和尾之和为素数{sum++;for(int i=0; i<q.size(); i++){cout<<q[i]<<" ";}cout<<endl;return;}return;}for(int next=2; next<=n; next++){if(!visit[next] && fun(pre+next)){visit[next]=1;q.push_back(next);dfs(cur+1,next);q.pop_back(); //回溯返回上一步visit[next]=0;}}return;
}
int main()
{cin>>n;if(n<2){cout<<"No Answer"<<endl;return 0;}q.push_back(1);visit[1]=1;dfs(1,1);if(sum==0){cout<<"No Answer"<<endl;}return 0;
}
3.小朋友的崇拜圈
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int N,temp,max1=0; //temp为寻找完整圈
int a[100010];
int v[100010]= {0};void dfs(int cur,int sum1)
{if(v[cur]) //访问过,存在闭合圈 {if(cur==temp) //真正的完整闭合圈 {if(max1<sum1){max1=sum1;}}return;}else{v[cur]=1;dfs(a[cur],sum1+1);v[cur]=0;}
}
int main()
{cin>>N;for(int i=1; i<=N; i++){cin>>a[i]; //第i个小朋友崇拜的人编号}for(int i=1; i<=N; i++){temp=i;dfs(i,0); //寻找每个小朋友的圈}cout<<max1<<endl; return 0;
}
4. 冰冰的正多边形
此题不是dfs算法,回顾的哈希算法
#include<bits/stdc++.h>
using namespace std;
int t,n;
int main()
{cin>>t;while(t--){cin>>n;int a[20],x[110];vector<int>nums;memset(a,0,sizeof(a));memset(x,0,sizeof(x));for(int i=0; i<n; i++){cin>>a[i];}for(int i=0; i<n; i++){x[a[i]]++;}for(int i=0;i<110;i++){if(x[i]>=3){nums.push_back(i*3);}}sort(nums.begin(),nums.end());if(nums.size()!=0){cout<<"yes"<<endl<<nums[0]<<endl;}else{cout<<"no"<<endl;}nums.clear();}return 0;
}
5.特殊的多边形
//求出组合它的个n边形(乘积为n)所有可能的不同边长组合
//考虑到n边形边长的限制和乘积范围,使用dfs枚举所有的边长组合
//题目要求边长互不相同,所以边长大小保证为从小到大,即每次添加的新边都大于之前的所有边
//dfs构建出完整的n边形,记录其乘积值到 cnt 数组
//前缀和prefix[]快速求出[l,r]区间内合适的n边形
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n;
int cnt[N],prefix[N]; //cnt[i] 表示乘积为i的多边形个数void dfs(int dep,int st,int mul,int sum) //dep当前处理到第几条边,st上一条边的长度,mul当前已有的边长乘积,sum是当前边长之和
{if(mul>1e5) return; //剪枝1if(dep==n+1){cnt[mul]++;return;}int up=pow(1e5/mul,1.0/(n-dep+1))+3; //剪枝2(算边长上限)//剪枝3(算边长下限)//最后一位的长度不能超过sum,也不能超过up//即多边形前n-1条边和大于第n条边,第n条边要小于前n-1条边之和for (int i = st + 1; i < (dep == n ? min(sum, up) : up); i++){dfs(dep + 1, i, mul * i, sum + i);}
}
int main()
{cin>>t>>n;dfs(1,0,1,0);for(int i=1; i<=1e5; i++){prefix[i]=prefix[i-1]+cnt[i];}while(t--){int l,r;cin>>l>>r;cout<<prefix[r]-prefix[l-1]<<endl;}return 0;
}