P2404 自然数的拆分问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
明目张胆的搜索题目,把每层搜索的值都相加,当等于目标值就收集输出结果。
每次搜索接着上一个数开始都从一开始会重复。
#include<bits/stdc++.h>
using namespace std;
int n,a[10]={0};
void dfs(int start,int sum,int t);
int main()
{
scanf("%d",&n);
dfs(1,0,1);
}
void dfs(int start,int sum,int t)
{
int i;
if(sum==n)
{
if(t-1==1)return;//防止输出7
for(i=1;i<t;i++)
{
if(i==1)printf("%d",a[i]);
else printf("+%d",a[i]);
}
cout<<endl;
return;
}
for(i=start;i<=n;i++)
{
if(sum+i<=n)//过滤不必要的搜索
{
sum+=i;
a[t++]=i;
dfs(i,sum,t);
sum-=i;
t--;//回溯
}
}
}
vs题解的大佬缩行大法:
#include<iostream>
using namespace std;
int a[10],n;
int p(int t)//打印
{
for(int j=1;j<=t-1;j++){cout<<a[j]<<"+";}
cout<<a[t]<<endl;
}
int js(int s,int t)
{
if(s==0){p(t-1);return 0;}
for(int k=1;k<=s;k++){if((a[t-1]<=k)&&(k<n)){a[t]=k,s=s-k;js(s,t+1);s=s+k;}}//深搜
}
int main()
{
cin>>n;
js(n,1);
}
P1294 高手去散步 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
将每一个地方都作为搜索的开始(因为高手有时光机)可以想象成一个图表(行列都是1到n)搜索,从左到右搜索可以去的地方,将去过的地方标记,再下一个地方从头到尾搜索即可。
#include<stdio.h>
int a[21][21],b[21];
int n,m,max;
void dfs(int i,int sum);
int main()
{
scanf("%d %d",&n,&m);
int i,j;
for(i=0;i<m;i++)
{
int x,y,s;
scanf("%d %d %d",&x,&y,&s);
a[x][y]=a[y][x]=s;
}
for(i=1;i<=n;i++)//每个地方都作为开始
{
int sum=0;
dfs(i,sum);
}
printf("%d",max);
}
void dfs(int i,int sum)
{
int k;
b[i]=1;//标记
for(k=1;k<=n;k++)
{
if(a[i][k]&&b[k]==0)
{
sum+=a[i][k];//累加路程
if(sum>max)max=sum;//更新最大值
dfs(k,sum);//进入下一个地方
sum-=a[i][k];//回溯
}
}
b[i]=0;//也是回溯
}
P1706 全排列问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
数学全排列,搜索(dfs)的入门模板,
#include<stdio.h>
int a[10],book[10];
int n;
void dfs(int step);
int main()
{
scanf("%d",&n);
dfs(1);//以每一步进入搜索
}
void dfs(int step){
int k;
if(step==n+1)//排完输出
{
for(k=1;k<=n;k++)
{
printf("%5d",a[k]);//要求输出格式很坑
if(k%n==0)printf("\n");
}
return;
}
for(k=1;k<=n;k++)//寻找没排的数
{
if(book[k]==0)
{
book[k]=1;//标记
a[step]=k;//排数
dfs(step+1);//下一步
book[k]=0;//回溯
}
}
return;
}