Codeforces 793 D. Presents in Bankopolis

来源:互联网 发布:任子行网络审计 编辑:程序博客网 时间:2024/06/05 03:20


D. Presents in Bankopolis
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Bankopolis is an incredible city in which all the n crossroads are located on a straight line and numbered from 1 to n along it. On each crossroad there is a bank office.

The crossroads are connected with m oriented bicycle lanes (the i-th lane goes from crossroad ui to crossroad vi), the difficulty of each of the lanes is known.

Oleg the bank client wants to gift happiness and joy to the bank employees. He wants to visit exactly k offices, in each of them he wants to gift presents to the employees.

The problem is that Oleg don't want to see the reaction on his gifts, so he can't use a bicycle lane which passes near the office in which he has already presented his gifts (formally, the i-th lane passes near the office on the x-th crossroad if and only if min(ui, vi) < x < max(ui, vi))). Of course, in each of the offices Oleg can present gifts exactly once. Oleg is going to use exactly k - 1 bicycle lane to move between offices. Oleg can start his path from any office and finish it in any office.

Oleg wants to choose such a path among possible ones that the total difficulty of the lanes he will use is minimum possible. Find this minimum possible total difficulty.

Input

The first line contains two integers n and k (1 ≤ n, k ≤ 80) — the number of crossroads (and offices) and the number of offices Oleg wants to visit.

The second line contains single integer m (0 ≤ m ≤ 2000) — the number of bicycle lanes in Bankopolis.

The next m lines contain information about the lanes.

The i-th of these lines contains three integers ui, vi and ci (1 ≤ ui, vi ≤ n, 1 ≤ ci ≤ 1000), denoting the crossroads connected by the i-th road and its difficulty.

Output

In the only line print the minimum possible total difficulty of the lanes in a valid path, or -1 if there are no valid paths.

Examples
input
7 441 6 26 2 22 4 22 7 1
output
6
input
4 342 1 21 3 23 4 24 1 1
output
3
Note

In the first example Oleg visiting banks by path 1 → 6 → 2 → 4.

Path 1 → 6 → 2 → 7 with smaller difficulity is incorrect because crossroad 2 → 7 passes near already visited office on the crossroad6.

In the second example Oleg can visit banks by path 4 → 1 → 3.

题意:有n个点分为别1~n,m条带权有向边,从中取k个点,要求里面存在一条路径经过所有的点一次并且不能跨过已经走过的点,打个比方,走了这么一条路1->3->5,那么剩下能走的就剩4和5以后的点了。因为最后一步是3->5,所以不能向左走不能跨过3,只能走到4,向右走这种情况下并没有限制。本人描述能力有点弱,还是看不懂题的话我也没办法了。问题就是求这样的最短路径。

思路:我第一眼就看出是区间dp。。。但是我居然调了差不多两个小时,醉了。。。而且题目还会出现重边,好吧我服。其实倒过来想一下就知道也就4种情况,dp[i][j][k][2]表示区间I,j经过k个点的最短路径,第四维的0表示当前位置在区间的左边,1在右边。具体怎么转移不好说明,还是看代码吧。

#include<iostream>  #include<cmath>  #include<queue>  #include<cstdio>  #include<queue>  #include<algorithm>  #include<cstring>  #include<string>  #include<utility>#include<map>#include<vector>#define maxn 85#define inf 0x3f3f3f3fusing namespace std;typedef long long LL;const double eps = 1e-5;int value[maxn][maxn];int dp[maxn][maxn][maxn][2];int main(){memset(value, inf, sizeof(value));int n, k, m;scanf("%d%d%d", &n, &k, &m);for (int i = 0; i < m;i++){int u, v, w;scanf("%d%d%d", &u, &v, &w);value[u][v] = min(value[u][v], w);}memset(dp, inf, sizeof(dp));for (int i = 1; i <= n; i++)dp[i][i][1][0] = dp[i][i][1][1] = 0;for (int i = 1; i < n; i++){for (int j = 1; j + i <= n; j++){for (int kk = j; kk < j + i; kk++){if (value[i + j][j] != inf)for (int l = 2; l <= k; l++)dp[j][i + j][l][1] = min(dp[j][i + j][l][1], dp[j][kk][l - 1][0] + value[i + j][j]);if (value[i + j][kk]!=inf)for (int l = 2; l <= k; l++)dp[j][i + j][l][1] = min(dp[j][i + j][l][1], dp[j][kk][l - 1][1] + value[i + j][kk]);}for (int kk = j + 1; kk <= j + i; kk++){if (value[j][i + j] != inf)for (int l = 2; l <= k; l++)dp[j][i + j][l][0] = min(dp[j][i + j][l][0], dp[kk][j + i][l - 1][1] + value[j][j + i]);if (value[j][kk] != inf)for (int l = 2; l <= k; l++)dp[j][i + j][l][0] = min(dp[j][i + j][l][0], dp[kk][j + i][l - 1][0] + value[j][kk]);}}}int ans = inf;for (int i = 1; i <= n; i++){for (int j = i; j <= n; j++){ans = min(ans, dp[i][j][k][0]);ans = min(ans, dp[i][j][k][1]);}}if (ans == inf)ans = -1;printf("%d\n", ans);}

0 0
原创粉丝点击