基础算法--递归搜索DFS练习总结(中)

洛谷部分练习:

P2089 烤鸡

暴力 code:

#include<iostream>
using namespace std;
#define ll long long
int main() {
	ll n, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, cnt = 0, flag = 0;
	cin >> n;
	for (i1 = 1; i1 <= 3; i1++) {
		for (i2 = 1; i2 <= 3; i2++) {
			for (i3 = 1; i3 <= 3; i3++) {
				for ( i4 = 1; i4 <= 3; i4++) {
					for (i5 = 1; i5 <= 3; i5++) {
						for (i6 = 1; i6 <= 3; i6++) {
							for (i7 = 1; i7 <= 3; i7++) {
								for ( i8 = 1; i8 <= 3; i8++) {
									for ( i9 = 1; i9 <= 3; i9++) {
										for (i10 = 1; i10 <= 3; i10++) {
											if (i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10==n) {
												flag = 1;
												cnt++;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	if (flag == 0)
		cout << flag;
	if (flag == 1)
		cout << cnt << endl;
	for (i1 = 1; i1 <= 3; i1++) {
		for (i2 = 1; i2 <= 3; i2++) {
			for (i3 = 1; i3 <= 3; i3++) {
				for (i4 = 1; i4 <= 3; i4++) {
					for (i5 = 1; i5 <= 3; i5++) {
						for (i6 = 1; i6 <= 3; i6++) {
							for (i7 = 1; i7 <= 3; i7++) {
								for (i8 = 1; i8 <= 3; i8++) {
									for (i9 = 1; i9 <= 3; i9++) {
										for (i10 = 1; i10 <= 3; i10++) {
											if (i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 == n) {
												cout << i1 << " " << i2 << " " << i3 << " " << i4 << " " << i5 << " " << i6 << " " << i7 << " " << i8 << " " << i9 << " " << i10 << endl;
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
}

DFS code:

#include<iostream>
#include<cstring>
using namespace std;
int n,ans[11],cnt;
void dfs(int x){
    if(x>10){
        int sum=0;
        for(int i=1;i<=10;i++) sum+=ans[i];
        if(sum==n) cnt++;
        return ;
    }
    ans[x]=1;
    dfs(x+1);
    ans[x]=2;
    dfs(x+1);
    ans[x]=3;
    dfs(x+1);
}
void dfss(int x){
    if(x>10){
        int sum=0;
        for(int i=1;i<=10;i++) sum+=ans[i];
        if(sum==n) {
            for(int i=1;i<=10;i++) cout<<ans[i]<<" ";
            cout<<endl;
        }
        return ;
    }
    ans[x]=1;
    dfss(x+1);
    ans[x]=2;
    dfss(x+1);
    ans[x]=3;
    dfss(x+1);
}
int main(){
    cin>>n;
    if(n<10||n>30) {cout<<"0"<<endl;return 0;}
    dfs(1);
    cout<<cnt<<endl;
    memset(ans,0,sizeof(ans));
    dfss(1);
    return 0;
}

P1088 [NOIP2004 普及组] 火星人

DFS code:

#include<iostream>
using namespace std;
const int N=10005;
int n,m,a[N],ans[N],cnt;
bool flag[N],key;
void dfs(int x){
    //输出后无需继续搜素
    if(key) return ;
    if(x>n){
        cnt++;
        if(cnt==m+1){
            for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
            cout<<endl;
            key=true;
        }
        return ;
    }
    for(int i=1;i<=n;i++){
        //刚开始把火星人给的数进行存储
        if(cnt==0) i=a[x];
        if(flag[i]==false){
            flag[i]=true;
            ans[x]=i;
            dfs(x+1);
            flag[i]=false;
            ans[x]=0;
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    dfs(1);
    return 0;
}

库函数 code:

#include<iostream>
#include<algorithm>
using namespace std;
int n, m, a[10005];
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	for (int i = 1; i <= m; i++)
		next_permutation(a, a + n);
	for (int i = 0; i <= n - 2; i++)
		cout << a[i] << " ";
	cout << a[n - 1];
	return 0;
}

P1149 [NOIP2008 提高组] 火柴棒等式

暴力 code:

#include<iostream>
using namespace std;
int match[10]={6,2,5,5,4,5,6,3,7,6},n,ans;
int fun(int x){
    if(x<=9) return match[x];
    else{
        int temp=0;
        while(x>0){
            temp+=match[x%10];
            x/=10;
        }
        return temp;
    }
}
int main(){
    cin>>n;n-=4;
    for(int i=0;i<=1000;i++){
        for(int j=0;j<=1000;j++){
            if(i!=j){
                int t=i+j;
                if(n==fun(i)+fun(j)+fun(t)){
                    ans++;
                }
            }
        }
    }
    for(int i=0;i<=1000;i++){
        int t=i+i;
        if(n==2*fun(i)+fun(t)){
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

DFS code:

#include<iostream>
using namespace std;
int n,ans,a[10005],match[10]={6,2,5,5,4,5,6,3,7,6};
int fun(int z){
    if(z<=9) return match[z];
    else{
        int temp=0;
        while(z>0){
            temp+=match[z%10];
            z/=10;
        }
        return temp;
    }
}
void dfs(int x,int sum){
    //火柴数用尽无需继续搜素
    if(sum>n) return ;
    //选够三个
    if(x>3){
        if(a[1]+a[2]==a[3]&&sum==n){ //满足两个条件就计数
            ans++;
        }
        return ;
    }
    //遍历要从0开始
    for(int i=0;i<=1000;i++){
        a[x]=i;
        dfs(x+1,sum+fun(i));
        a[x]=0;
    }
}
int main(){
    cin>>n;n-=4;
    dfs(1,0);
    cout<<ans<<endl;
    return 0;
}

P2036 [COCI2008-2009 #2] PERKET

类型: 递归实现指数型枚举

DFS code:

#include<iostream>
#include<cmath>
using namespace std;
const int N=11;
int n,a[N],b[N],flag[N],minn=1e5;
void dfs(int x){
    if(x>n){
        int sum1=1,sum2=0,key=0;
        //值得注意的是,存在一种全不选择的情况,故用key来判断
        for(int i=1;i<=n;i++){
            if(flag[i]==1){
                key=1;
                sum1*=a[i];
                sum2+=b[i];
            }
        }
        //只有全不为空的情况才更新答案
        if(key==1) minn=min(minn,abs(sum2-sum1));
        return ;
    }
    //递归实现指数型枚举
    flag[x]=0; //不选
    dfs(x+1);
    flag[x]=1; //选
    dfs(x+1);
}
int main(){
    cin>>n; for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
    dfs(1);
    cout<<minn<<endl;
    return 0;
}

P1135 奇怪的电梯

DFS code (64 points) :

#include<iostream>
using namespace std;
int n,a,b,k[205],ans=1e6,flag[205];
//当前在第x楼,按了cnt次按钮
void dfs(int x,int cnt){
    if(cnt>=ans) return ;
    //到达就终止递归
    if(x==b){
        ans=min(ans,cnt);
        return ;
    }
    flag[x]=1;
    if(x+k[x]<=n&&flag[x+k[x]]==0){ //上楼
        flag[x+k[x]]=1;
        dfs(x+k[x],cnt+1);
        flag[x+k[x]]=0;
    }
    if(x-k[x]>=1&&flag[x-k[x]]==0){ //下楼
        flag[x-k[x]]=1;
        dfs(x-k[x],cnt+1);
        flag[x-k[x]]=0;
    }
}
int main(){
    cin>>n>>a>>b;
    for(int i=1;i<=n;i++) cin>>k[i];
    dfs(a,0);
    //无法到达输出-1
    if(ans==1e6) {cout<<"-1"<<endl; return 0;}
    cout<<ans<<endl;
    return 0;
}
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值