挖地雷

挖地雷

https://www.luogu.com.cn/problem/P2196

前言:

emmm...最开始接触这道题,是在学深搜的时候(具体哪本书忘了)那时候还做不来,就听老师讲了之后直接交的代码,并没有多大的感悟。

为了CSP,又开始复习(重学)万能的深搜;再加上想练习一下 vector ,于是重新编了一遍。交了三遍AC了。


思路:

1、题目中:“某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。”

很明显就是 DFS嘛!尝试所有N个洞作为起始点,不断探索与之相连的点(洞),把每一种方案的结果记录下来再比较最大,完事!

2、不过,这道题还要求输出最大值的路径。我认为这才是这道题的难点(最大值直接套深搜板子就好)。那就用一个数组 nxt记录路径。每当更新最多地雷数的时候,顺便也将路径更新。当然,要用另外一个数组sum保存。

具体的见代码注释吧

#include <bits/stdc++.h>
using namespace std;
int n,x,k,ans,tot,nxt[10010],a[10010],sum[10010],p[10010];
vector<int> ssty[10010];

inline void dfs(int x,int y,int tot) { //x记录位置,走了y个点,tot是当前的地雷数
	bool pd=false; //判断当前方案是否走到极点
	for(register int i=0; i<ssty[x].size(); i++) { //与x点相连的点
		if(p[ssty[x][i]]==0) { //没有走过
			pd=true; //方案没有结束
			p[ssty[x][i]]=1; //标记为走过
			nxt[y+1]=ssty[x][i]; //记录路径
			dfs(ssty[x][i],y+1,tot+a[ssty[x][i]]); //从这个点继续向下挖
			p[ssty[x][i]]=0; //回溯必备
		}
	}
	if(pd==false) {
		if(ans<tot) { //如果最大值更改,说明路径也要改变
			ans=tot;
			k=y;
			for(register int i=1; i<=y; i++) sum[i]=nxt[i]; //将最大值路径复制在sum数组中
		}
		return;
	}
}

int main() {
	scanf("%d",&n);
	for(register int i=1; i<=n; i++) scanf("%d",&a[i]);
	for(register int i=1; i<n; i++) { //题目要求的输入
		for(register int j=i+1; j<=n; j++) {
			scanf("%d",&x);
			if(x==1) ssty[i].push_back(j); //将与 i 洞相连的点加入“队列”
		}
	}
	for(register int i=1; i<=n; i++) { //尝试每一个点
		p[i]=1; //标记为已走过
		nxt[1]=i; //将第一个洞设为自己
		dfs(i,1,a[i]);
		p[i]=0;
	}
	for(register int i=1; i<=k; i++) printf("%d ",sum[i]); //最终的最大值路径
	printf("\n%d",ans); //最多能挖到的地雷数
	return 0;
}

深搜,一种把板子套上去就差不多成功一半的神奇算法QVQ

如果这篇题解有任何问题,欢迎指正,谢谢!

posted @ 2020-06-08 13:28  Eleven谦  阅读(206)  评论(0编辑  收藏  举报