深搜 dfs 手算到机算 入门 排列数

深搜 dfs 手算到机算 入门  排列数

总目录:从手算到机算 算法竞赛入门篇

 

1.洛谷 P1706 全排列问题

 AC代码(标准代码)如下:

#include <bits/stdc++.h>
int n,a[20],vis[20];
void dfs(int step){
	int i;
	if(step==n+1){
		int j;
		for(j=1;j<=n;j++)printf("%5d",a[j]);
		printf("\n");
		return;
	}
	for(i=1;i<=n;i++)
		if(!vis[i]){
			vis[i]=1;
			a[step]=i;
			dfs(step+1);
			vis[i]=0;
		} 
}
int main(){
	scanf("%d",&n);
	dfs(1); 
	return 0;
}

上述 标准代码 执行样例 的手算过程 如下:

输入:
3
输出:
    1    2    3
    1    3    2
    2    1    3
    2    3    1
    3    1    2
    3    2    1

初始:
数组vis位置1 2 3
数组vis数值0 0 0

数组a位置  1 2 3
数组a数值  0 0 0

第1次执行完毕:
数组vis位置1 2 3
数组vis数值1 0 0

数组a位置  1 2 3
数组a数值  1 0 0

第2次执行完毕:
数组vis位置1 2 3
数组vis数值1 1 0

数组a位置  1 2 3
数组a数值  1 2 0

第3次执行完毕:
数组vis位置1 2 3
数组vis数值1 1 1

数组a位置  1 2 3
数组a数值  1 2 3

打印:    1    2    3

第4次执行完毕:
数组vis位置1 2 3
数组vis数值1 0 1

数组a位置  1 2 3
数组a数值  1 3 3

第5次执行完毕:
数组vis位置1 2 3
数组vis数值1 1 1

数组a位置  1 2 3
数组a数值  1 3 2

打印:    1    3    2

第6次执行完毕:
数组vis位置1 2 3
数组vis数值0 1 0

数组a位置  1 2 3
数组a数值  2 3 2

第7次执行完毕:
数组vis位置1 2 3
数组vis数值1 1 0

数组a位置  1 2 3
数组a数值  2 1 0

第8次执行完毕:
数组vis位置1 2 3
数组vis数值1 1 1

数组a位置  1 2 3
数组a数值  2 1 3

打印:    2    1    3

以下依次类推......

以下代码为针对n=3时的循环代码写法,有助于理解深搜dfs的实现过程。

#include <bits/stdc++.h>
int n,a[20],vis[20];
int main(){
	int i1,i2,i3;
	n=3; 
	for(i1=1;i1<=n;i1++)//对应dfs中step=1的情况 
		if(!vis[i1]){
			vis[i1]=1;
			a[1]=i1;
			for(i2=1;i2<=n;i2++)//对应dfs中step=2的情况 
				if(!vis[i2]){
					vis[i2]=1;
					a[2]=i2;
					for(i3=1;i3<=n;i3++){//对应dfs中step=3的情况 
						if(!vis[i3]){
							vis[i3]=1;
							a[3]=i3;
							for(int j=1;j<=n;j++)printf("%5d",a[j]);
							printf("\n");
							vis[i3]=0;
						}
					}
					vis[i2]=0;
				}
			vis[i1]=0;
		} 
	return 0;
}

2.洛谷 P1008 三连击

 AC代码如下:

#include <stdio.h>
#include <string.h>
int a[10];
int visited[10];
int n=9;
void dfs(int step){
    int b,c,d;
    int i;
    b=a[1]*100+a[2]*10+a[3];
    c=a[4]*100+a[5]*10+a[6];
    d=a[7]*100+a[8]*10+a[9];
    if(step==n+1){
        if(c==2*b&&d==3*b)
            printf("%d %d %d\n",b,c,d);
        return;
    }
    for(i=1;i<=9;i++)
        if(visited[i]==0){
            a[step]=i;
            visited[i]=1;
            dfs(step+1);
            visited[i]=0;
        }
}
int main(){
    memset(visited,0,sizeof(visited));
    dfs(1);
    return 0;
} 

3.洛谷 P1618 三连击(升级版)

  AC代码如下:

#include <stdio.h>
#include <string.h>
int A,B,C;
int a[10],vis[10];
int count=0; 
void dfs(int step){
    int i;
    int b1,b2,b3;
    if(step==10){
        b1=a[1]*100+a[2]*10+a[3];
        b2=a[4]*100+a[5]*10+a[6];
        b3=a[7]*100+a[8]*10+a[9];
        if(b1*B*C==b2*A*C&&b2*A*C==b3*A*B){
            count++;
            printf("%d %d %d\n",b1,b2,b3);
        }
    }
    for(i=1;i<=9;i++)
        if(vis[i]==0){
            vis[i]=1;
            a[step]=i;
            dfs(step+1);
            vis[i]=0;
        }
}
int main(){
    memset(vis,0,sizeof(vis));
    scanf("%d%d%d",&A,&B,&C);
    dfs(1);
    if(count==0)
        printf("No!!!\n");
    return 0;
} 

4.洛谷 P1036 选数

   AC代码如下:

#include <stdio.h>
int a[25],b[25],cnt,n,k;
int isPrime(int x){
	if(x==1)return 0;
	if(x==2)return 1;
	for(int i=2;i*i<=x;i++)
		if(x%i==0)return 0;
	return 1;
}
void dfs(int step){
	int i;
	if(step==k+1){
		int j,sum=0;
		for(j=1;j<=k;j++)sum+=a[b[j]];
		if(isPrime(sum))cnt++;
		return ;
	}
	for(i=b[step-1]+1;i<=n;i++)
		b[step]=i,dfs(step+1);
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	b[0]=0,dfs(1);
	printf("%d\n",cnt);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值