• 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 }
  • 相关阅读:
    MySQL存储引擎InnoDB与Myisam的六大区别
    PHP+mysql防止SQL注入
    HTTPS 的实现原理
    如何保障 API 接口的安全性?
    使用Merge存储引擎实现MySQL分表
    彻底搞懂Reactor模型和Proactor模型
    REDIS集群脑裂以及解决方案
    linux shell文件合并 去重 分割
    python fnmatch & glob
    sed初理多行合并+sed之G、H、g、h使用+sed n/N使用说明
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6915380.html
Copyright © 2020-2023  润新知