暴搜简单DP挖地雷

Posted 行码棋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暴搜简单DP挖地雷相关的知识,希望对你有一定的参考价值。

链接:

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

几个点中有一系列路径,一个人可以从某个点开始走,直到走到尽头,每个点有一个值,问能够得到的最大值为多少

因为数据量较小,所以可以进行暴搜


1️⃣暴搜

  • 可以以每个点为起点 : 所以在dfs记录一些东西时需要进行回溯,本题需要回溯的是cnt值(记录了路径中的个数)
  • g [ i ] [ j ] g[i][j] g[i][j]代表ij是否可达
  • v : 记录路径的数组
  • sum:代表以当前点结尾的路径中值的总和
  • 注意刚开始的起点cnt也要回溯

暴搜

#include<bits/stdc++.h>
using namespace std;

using ll = long long;
bool g[21][21],vis[30]; 
int a[25];
int p[25];

int main()

	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	memset(g, false, sizeof(g));
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 2; i <= n; i++) 
	
		for(int j = i; j <= n; j++)
		
			int x;
			cin >> x;
			g[i - 1][j] = x;
		
	
	int ans = 0;
	vector<int> v;
	int cnt = 0;
	
	function<void(int, int)> dfs = [&](int x, int sum) -> void
	
		for(int i = x + 1; i <= n; i++)
		
			if(g[x][i])
			
				p[++ cnt] = i;
				dfs(i, sum + a[i]);
				cnt --; 
			
		
		if(sum > ans)
		
			ans = sum;
			v.clear();
			for(int i = 1; i <= cnt; i++) v.push_back(p[i]);
		
	;
	for(int i = 1; i <= n; i++)
	
		p[++ cnt] = i;
		dfs(i, a[i]);
		cnt --;
	
	for(int i = 0; i < v.size(); i++)
		cout << v[i] << " \\n"[i == v.size() - 1]; 
	cout << ans << "\\n";
	return 0;


2️⃣DP

状态表示:
f [ i ] f[i] f[i]:以i为结尾的路径中总和的最大值
状态转移:
f [ i ] = m a x ( f [ j ] + a [ i ] , f [ i ] ) = m a x ( f [ j ] ) + a [ i ] f[i] = max(f[j] + a[i],f[i]) = max(f[j]) + a[i] f[i]=max(f[j]+a[i],f[i])=max(f[j])+a[i]

因为需要记录路径,进行状态转移时需要设置一个pre数组存储路径中的前驱节点,最后是用递归输出路径。

同时需要注意f[i]数组的初始化,因为有时候可以只选择一个点,如果没有初始化的话就会出错。

last:最优结果中路径的结尾节点

#include<bits/stdc++.h>
using namespace std;


int main()

	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int n;
	cin >> n;
	vector<int>a(n + 1),f(n + 1);
	vector g(n + 1, vector(n + 1, 0));
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1; i < n; i++)
		for(int j = i + 1; j <= n; j++)
		
			int x;
			cin >> x;
			g[i][j] = x;
		
	
	vector<int> pre(n + 1, 0);
	int res = 0;
	int last = 0;
	
	for(int i = 1; i <= n; i++) f[i] = a[i];
	
	for(int i = 2; i <= n; i++)
	
		for(int j = 1; j < i; j++)
		
			if(g[j][i] && f[j] + a[i] > f[i])
			
				f[i] = f[j] + a[i];
				pre[i] = j;
			
		
		if(f[i] > res)
		
			last = i;
			res = f[i];
		
	
	
	function<void(int)> print = [&](int x) -> void
	
		if(pre[x] == 0)
		
			cout << x ;
			return;
		
		print(pre[x]);
		cout << " " << x;
	;
	print(last);
	cout << "\\n" << res << "\\n";
	return 0;


以上是关于暴搜简单DP挖地雷的主要内容,如果未能解决你的问题,请参考以下文章

挖地雷——线性dp

挖地雷问题

挖地雷(记忆化搜索)

P2196 挖地雷

挖地雷

落谷 2196 挖地雷