解法:先将每个点之间的可达性用c[][]记录,为0的话代表可以直接走到。但是如果要进行像3 1 2 这样的走法的话必须要先经过他们中间的点2,否则是不能走的。
用c[i][j]记录i和j之间必须要经过的点。然后进行dfs搜索即可。
经过这道题,自己对dfs的递归过程又有了更加深刻的了解。一开始的时候对dfs里面的参数有些疑虑,-->像这样dfs(s[0],0),但是这样的话,每次都要先判断c[x][s[i]]
另附dfs生成全排列的算法,是这道题的原型。
用c[i][j]记录i和j之间必须要经过的点。然后进行dfs搜索即可。
经过这道题,自己对dfs的递归过程又有了更加深刻的了解。一开始的时候对dfs里面的参数有些疑虑,-->像这样dfs(s[0],0),但是这样的话,每次都要先判断c[x][s[i]]
这样是错误的。dfs(0,0)的话,因为0与1~9都是可以直接到达的(0是自己添加的),所以可以得出所有情况。还有就是想要记录路径的时候要注意,看注释。
#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,n,ans;
int s[20],path[20];
int c[20][20];
int vis[20];
int v[150000][12];
void dfs(int x,int sum)
{
if(sum>=n)
{
for(int i=0;i<n;i++)//记录路径
v[ans][i]=path[i];
ans++;
return ;
}
for(int i=0;i<n;i++)
{
if(!vis[s[i]])
{
if(c[x][s[i]]==0)
{
path[sum]=s[i];
// v[ans][sum]=s[i]; ans前面的都为空,并未赋值,所以错误
vis[s[i]]=1;
dfs(s[i],sum+1);
vis[s[i]]=0;
}
else if(c[x][s[i]]&&vis[c[x][s[i]]]==1)
{
path[sum]=s[i];
//v[ans][sum]=s[i];
vis[s[i]]=1;
dfs(s[i],sum+1);
vis[s[i]]=0;
}
}
}
}
int main()
{
memset(c,0,sizeof(c));
c[1][3]=2,c[3][1]=2;
c[1][7]=4,c[7][1]=4;
c[1][9]=5,c[9][1]=5;
c[2][8]=5,c[8][2]=5;
c[3][9]=6,c[9][3]=6;
c[3][7]=5,c[7][3]=5;
c[4][6]=5,c[6][4]=5;
c[7][9]=8,c[9][7]=8;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(vis,0,sizeof(vis));
ans=0;
for(int i=0;i<n;i++)
scanf("%d",&s[i]);
sort(s,s+n);
dfs(0,0);//0与所有的点都是连接可以到达的
printf("%d\n",ans);
for(int i=0;i<ans;i++)
{
printf("%d",v[i][0]);
for(int j=1;j<n;j++)
printf(" %d",v[i][j]);
printf("\n");
}
}
return 0;
}
另附dfs生成全排列的算法,是这道题的原型。
#include<iostream>
#include<cstring>
using namespace std;
int vis[10],n;
int ans[10];
void dfs(int sum)
{
if(sum>n)
{
int first=0;
for(int i=1;i<=n;i++)
{
if(first++)
cout<<" ";
cout<<ans[i];
}
cout<<endl;
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
vis[i]=1;
ans[sum]=i;
dfs(sum+1);
vis[i]=0;
}
}
}
int main()
{
cin>>n;
memset(vis,0,sizeof(vis));
dfs(1);
}
dfs()里面的参数只用记录当前总数即可。也可采取在主程序中枚举起点的办法。