标签:now no int res 代码 dfs 端点 crossing include
no crossing(代码源每日一题)
no crossing - 题目 - Daimayuan Online Judge
区间DP
- 从暴力思路入手,站在 now 号点,当前可行的区间是 [l, r], 还要走 k 步,因此状态数为 \(n^4\), 总转移复杂度为 \(m\), 总复杂度为 \(n^4+m\)
- 因为路径的性质,不能横跨已经走过的点,因此 now 号点一定是下一个区间的左/右端点,因此可简化掉 now 这个状态, 总复杂度为 \(n^3+m\)
记 \(f[l][r][k][0/1]\) 表示当前能走的区间为 (l, r), 还有 k 步,当前站在左端点(0)还是右端点(1)
起始状态为枚举一开始站在 i 号点,i 为左端点还是右端点,即 \(dfs(0,i,k-1,1)\) 与 \(dfs(i,n+1,k-1,0)\)
注意此处边界为 0 和 n + 1,因为边界总是之前的点走过的或者 1,n,为了方便,设 dfs 的过程中令边界都不能取,所以一开始的边界为 0,n + 1,就保证了 1,n 是可取的
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
#define endl "\n"
typedef long long ll;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 110;
int f[N][N][N][2];//f[l][r][k][0/1]为当前可行的区间是[l,r],还要走k步,当前在l/r点
struct Edge
{
int to, val;
};
vector<vector<Edge> > G(N);
int n, k, m;
void add(int u, int v, int w)
{
G[u].push_back({v, w});
}
int dfs(int l, int r, int k, int d)
{
if (k <= 0)
return 0;
int &now = f[l][r][k][d];
if (~now)
return now;
int u = (d ? r : l);
int res = INF;
for (auto [v, w] : G[u])
{
if (v <= l || v >= r)
continue;
res = min(res, w + dfs(v, r, k - 1, 0));
res = min(res, w + dfs(l, v, k - 1, 1));
}
return now = res;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> k >> m;
while(m--)
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
}
int ans = INF;
memset(f, -1, sizeof f);
for (int i = 1; i <= n; i++)
{
ans = min(ans, dfs(i, n + 1, k - 1, 0));
ans = min(ans, dfs(0, i, k - 1, 1));
}
cout << (ans == INF ? -1 : ans) << endl;
return 0;
}
标签:now,no,int,res,代码,dfs,端点,crossing,include 来源: https://www.cnblogs.com/hzy717zsy/p/16368390.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。