本文主要是介绍动态规划+深度优先搜索——挖地雷(洛谷 P2196),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目选自洛谷P2196
本题是一道基础的练习题,可以采用动态规划和DFS的方法来求解。
动态规划的解题思路:
DFS的解题思路:
由于只能从数字小的到数字比它大的地方走,所以for i从出发点+1开始,如果有路且没走过就走,更新一下总数。
当总数比之前某一次的值大,我们就更新一下路径和总数。
用a[21]来记录最终的结果,用b[21]来保存每种dfs的路径,更新路径就是把b数组赋给b数组
dfs(int x,int y,int ans) //x表示当前在第x点,y为走了多少个点,ans为当前雷的总数
走过一个点就标记,走完之后记得回溯一下即可
题目描述
在一个地图上有N个地窖(N≤20),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。
输入格式
有若干行。
第1行只有一个数字,表示地窖的个数N。
第2行有N个数,分别表示每个地窖中的地雷个数。
第3行至第N+1行表示地窖之间的连接情况:
第3行有n−1个数(0或1),表示第一个地窖至第2个、第3个、…、第n个地窖有否路径连接。如第3行为11000…0,则表示第1个地窖至第2个地窖有路径,至第3个地窖有路径,至第4个地窖、第5个、…、第n个地窖没有路径。
第4行有n−2个数,表示第二个地窖至第3个、第4个、…、第n个地窖有否路径连接。
… …
第n+1行有1个数,表示第n−1个地窖至第n个地窖有否路径连接。(为0表示没有路径,为1表示有路径)。
输出格式
有两行
第一行表示挖得最多地雷时的挖地雷的顺序,各地窖序号间以一个空格分隔,不得有多余的空格。
第二行只有一个数,表示能挖到的最多地雷数。
输入输出样例
输入 1
5 10 8 4 7 6 1 1 1 0 0 0 0 1 1 1
输出 1
1 3 4 5 27
说明/提示
【题目来源】
NOIP 1996 提高组第三题
解题代码:(动态规划版)
#include<stdio.h>
#include<iostream>
using namespace std;
int n,a[21][21];
int f[21],w[21],q[21],ans[21];
int main(){cin>>n;for(int i=1;i<=n;i++) {scanf("%d",&w[i]); f[i]=w[i];}//雷的数目for(int i=1;i<n;i++)for(int j=i+1;j<=n;j++)scanf("%d",&a[i][j]);for(int i=1;i<=n;i++)for(int j=1;j<i;j++)if(a[j][i]){if(f[j] + w[i] > f[i]){f[i] = f[j] + w[i];q[i] = j;}}int x=0,tot=0;for(int i=1;i<=n;i++)if(f[x]<f[i]) x = i;ans[0] = f[x];while(x){ ans[++tot] = x; x=q[x];}for(int i=tot;i>1;i--) printf("%d ",ans[i]);printf("%d",ans[1]);printf("\n%d",ans[0]);return 0;
}
解题代码: (DFS版)
#include<stdio.h>
#include<iostream>
using namespace std;
int n,cnt=-999,v,k; //k保存结果应该是几个数
int f[21][21],book[21];
int lei[21];
int a[21],b[21]; //a是结果,b用来每次dfs记录路径
/* 只能从右下进行遍历 */
void dfs(int x,int y,int ans){ //x为位置,y为走了多少个点,ans为雷的总数b[y] = x; //保存路径if(ans > cnt){ //更新路径for(int i=1;i<=y;i++)a[i] = b[i];cnt = ans;k = y;}for(int i=x+1;i<=n;i++){if(f[x][i] && book[i]==0){book[i] = 1;dfs(i,y+1,ans+lei[i]);book[i] = 0;}}
}
int main(){cin>>n;for(int i=1;i<=n;i++) cin>>lei[i];for(int i=1;i<n;i++) //保存图for(int j=i+1;j<=n;j++){scanf("%d",&f[i][j]);}for(int i=1;i<=n;i++){ //每个点都作为起点dfs一次book[i] = 1; b[1]=i;dfs(i,1,lei[i]);book[i] = 0;}for(int i=1;i<=k;i++)printf("%d ",a[i]);printf("\n%d",cnt);return 0;
}
这篇关于动态规划+深度优先搜索——挖地雷(洛谷 P2196)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!