Codeforces 793 D. Presents in Bankopolis
2017-04-27 22:38
316 查看
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
output
input
output
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 0x3f3f3f3f
using 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);
}
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 4 4 1 6 2 6 2 2 2 4 2 2 7 1
output
6
input
4 3 4 2 1 2 1 3 2 3 4 2 4 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 0x3f3f3f3f
using 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);
}
相关文章推荐
- 【codeforces 793D】Presents in Bankopolis
- Tinkoff Challenge - Elimination Round D. Presents in Bankopolis(区间DP)
- Presents in Bankopolis CodeForces - 793D
- CF-Tinkoff Challenge-Elimination Round-D-Presents in Bankopolis
- Codeforces 814D-An overnight dance in discotheque
- Codeforces 702E Analysis of Pathes in Functional Graph(倍增)
- [Codeforces 674F] Bears and Juice dp+巧妙的meet in the middle优化
- 【32.89%】【codeforces 719A】Vitya in the Countryside
- 【CODEFORCES】 B. Friends and Presents
- 【Codeforces809D】Hitchhiking in the Baltic States
- [Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]
- Codeforces 285E - Positions in Permutations 【题解待补全】
- Codeforces 263 D. Cycle in Graph 环
- CodeForces 479 E. Riding in a Lift
- Codeforces 421D Bug in Code(思维)
- 【CodeForces】671 D. Roads in Yusland
- Codeforces 566 F. Clique in the Divisibility Graph
- 【codeforces 691 D】【并查集 或者 dfs】aps in Permutation【给一个1到N的排列,M个操作,每次可以交换X Y位置上的数字,求可以得到的最大字典序的数列】
- CodeForces 25D Roads not only in Berland
- codeforces水题100道 第十八题 Codeforces Round #289 (Div. 2, ACM ICPC Rules) A. Maximum in Table (brute force)