挖地雷问题 dfs

问题描述

在一个地图上有N个地窖(N<=12),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。

[题目要求]

当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,每个地窖只能经过一次,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。

输入格式

第一行一个数n。
第二行n个数wi表示每个点的地雷数。
随后n-1行若干个数。第i行第j个数表示i与i+j是否连通。1为连通,0为不连通。

输出格式

K1–K2–……….KV (挖地雷的顺序)
MAX=ans (挖地雷的数量)
如果有多种方案则输出字典序最小的方案。

样例输入
5
10 8 4 7 6
1 1 1 1
0 0 0
1 1
1

样例输出
2-1-3-4-5
MAX=35

数据规模和约定
n<=12

题解:如果不要求输出路径,则直接dfs暴力搜索就可以,若输出路径,则需要多加两个数组,to[]存过程中可以更新的路径,pre[]存最终路径,

无路径:

#include<stdio.h>
#include<string.h>
#define ma_x(a,b) a>b?a:b

int n,w[15],f[15][15],max,vis[15],dp[15];

int dfs(int i,int ans){
    int j,flag;
    for(j=1;j<=n;j++){
        flag=0;
        if(f[i][j]==1&&vis[j]==0){//两点连通,且该点没有访问过 
                vis[j]=1;
                dfs(j,ans+w[j]);
                vis[j]=0;
                flag=1;
        }
    }
    if(flag==0){ 
        max=ma_x(max,ans);
    } 
}

int main(){
    int i,j;
    scanf("%d",&n);

    //输入各地窖地雷数
    for(i=1;i<=n;i++){ 
        scanf("%d",&w[i]);
    }

    //地窖连通关系
    for(i=1;i<n;i++){ 
        for(j=i+1;j<=n;j++){
            scanf("%d",&f[i][j]);
            f[j][i]=f[i][j];
        }
        f[i][i]=0;
    }

    //核心代码,求从i点出发的寻找地雷的最大数 
    for(i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        vis[i]=1;
        max=w[i];
        dfs(i,w[i]);
        dp[i]=max;
    }
    max=0;

    //求能挖最大的地雷数,以及入口i 
    for(i=1;i<=n;i++){
        if(dp[i]>max){
            max=dp[i];
            j=i;    
        }
    }
    printf("%d\n",j);
    printf("%d",max);   
} 

有路径:

#include<stdio.h>
#include<string.h>

int n,w[15],f[15][15],max=0,vis[15],dp[15],to[15],pre[15],last;

int dfs(int i,int ans){
    int j,flag=0;
    ans=ans+w[i];
    for(j=1;j<=n;j++){
        if(f[i][j]==1&&vis[j]==0){//两点连通,且该点没有访问过
                to[j]=i;//经过i点到j ,记录路径 
                vis[j]=1;
                dfs(j,ans);
                to[j]=0;
                vis[j]=0;
                flag=1;
        }
    }
    if(flag==0){ 
        if(ans>max){//如果这条路挖的更多,更新路径 
            max=ans;
            last=i;//挖地雷工作结束的地窖 
            for(j=1;j<=n;j++){
                pre[j]=to[j];//记录路径 
            }
        }
    } 
}

//输出路径 
int path(int x){ 
    if(x==0) return 0;//找到起点 
    path(pre[x]);//去找起点 ,这部找到到x的上一个点 
    if(x!=last) printf("%d-",x);
    else printf("%d",x);
}

int main(){
    int i,j;
    scanf("%d",&n);

    //输入各地窖地雷数
    for(i=1;i<=n;i++){ 
        scanf("%d",&w[i]);
    }

    //地窖连通关系
    for(i=1;i<n;i++){ 
        for(j=i+1;j<=n;j++){
            scanf("%d",&f[i][j]);
            f[j][i]=f[i][j];
        }
        f[i][i]=0;
    }

    //核心代码,求从i点出发的寻找地雷的最大数 
    for(i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        memset(to,0,sizeof(to));
        vis[i]=1;
        dfs(i,0);
    }

    path(last); 
    printf("\nMAX=%d",max); 
} 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值