暴搜简单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]代表
i
到j
是否可达 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挖地雷的主要内容,如果未能解决你的问题,请参考以下文章