Tinkoff Challenge

http://codeforces.com/contest/793/problem/D

题意:
给出一些点和他们之间的距离,是有向的,这些点从1~n顺序排列,现在选出k个点组成一条路径,使他们之间的距离最短,要求是在路径中,一个被访问过的点不会经过两次或以上。

比如,你访问了1~6这条边,那么你已经访问了1和6这两个点,接下来你就不可以访问5~7这条边了,因为他们之间有6这个点。

思路:
区间dp题。

区间dp的话,递推和记忆化搜索都是可以的。

d【i】【l】【r】【dir】表示当前访问第i次时,在区间【l,r】内的最短距离,并且此时位于dir端,0表示在左端,1表示在右端。

那么这个状态肯定来源于它区间之内的状态。

现在我们假设temp是处于【l,r】之间一个点,那么【l,r】区间的最短距离可以来源于【l,temp】或者【temp,r】。

这样状态转移方程就是:

d[i][l][r][0]=min(d[i][l][r][0],d[i-1][l][temp][1]+dis);
d[i][l][r][0]=min(d[i][l][r][0],d[i-1][temp][y][0]+dis);

当然了,在右端时的状态转移方程也是差不多的。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #include<cmath>
 9 #include<map>
10 using namespace std;
11 typedef long long LL;
12 typedef pair<int,int> pll;
13 const int inf=0x3f3f3f3f;
14 const int maxn=80+5;
15 
16 int n,m,k;
17 int ans;
18 vector<pll> G[maxn];
19 int d[maxn][maxn][maxn][2];
20 
21 int main()
22 {
23     //freopen("D:\input.txt","r",stdin);
24     while(~scanf("%d%d",&n,&k))
25     {
26         
27         memset(d,0,sizeof(d));
28         for(int i=1;i<=n;i++)  G[i].clear();
29         ans=inf;
30 
31         scanf("%d",&m);
32         for(int i=1;i<=m;i++)
33         {
34             int u,v,w;
35             scanf("%d%d%d",&u,&v,&w);
36             G[u].push_back(make_pair(v,w));  //这样的话不需要考虑重边的问题
37         }
38         
39         if(k==1)  {puts("0");continue;}  //1的时候特判一下
40 
41         for(int i=1;i<k;i++)
42         {
43             for(int l=n;l>=0;l--)
44             {
45                 for(int r=l+1;r<=n+1;r++)
46                 {
47                     d[i][l][r][0]=inf;
48                     for(int j=0;j<G[l].size();j++)
49                     {
50                         int temp=G[l][j].first;
51                         int dis=G[l][j].second;
52                         if(l<temp && temp<r)
53                         {
54                             d[i][l][r][0]=min(d[i][l][r][0],d[i-1][l][temp][1]+dis);
55                             d[i][l][r][0]=min(d[i][l][r][0],d[i-1][temp][r][0]+dis);
56                         }
57                     }
58                     d[i][l][r][1]=inf;
59                     for(int j=0;j<G[r].size();j++)
60                     {
61                         int temp=G[r][j].first;
62                         int dis=G[r][j].second;
63                         if(l<temp && temp<r)
64                         {
65                             d[i][l][r][1]=min(d[i][l][r][1],d[i-1][l][temp][1]+dis);
66                             d[i][l][r][1]=min(d[i][l][r][1],d[i-1][temp][r][0]+dis);
67                         }
68                     }
69                     if(i==k-1)
70                     {
71                         ans=min(ans,d[i][l][r][0]);
72                         ans=min(ans,d[i][l][r][1]);
73                     }
74                 }
75             }
76         }
77         if(ans==inf)  puts("-1");
78         else printf("%d
",ans);
79     }
80     return 0;
81 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6915380.html