zoukankan      html  css  js  c++  java
  • Tinkoff Challenge

    传送门

    题意

    给出n条有项边,且点都在一条直线上从1到n编号,询问走过k-1条边的最短距离,注意,走的过程中不能经过先前访问过的点,比如1->3->5->2不行,在到达2
    的时候经过了已访问点3

    分析

    区间DP,dp[l][r][dir][step]表示l到r方向为dir步数为step的最短距离,我们呢可以递归求解,dp[l][r][dir][step]由dp[l][i][1][step+1]+c[r][i]和dp[i][r][0][step+1]+c[l][i]转移过来,一开始dp[0][n+1][dir][0]

    Oleg can't go near offices he visited, so if now he is in office v, he visited q, q > v, he can't visit office k, where k > q. That means if now he's in office v, he can only visit office q, l < v < r, l is rightmost visited office which position is less than v and r is leftmost visited office which position is more than v. So we have to solve our problem for state [v][l][r][s], where s count of steps we made. We have 2 options. First is go to left and second is go to right. If we go left, we are not interested what is r, and if we go right we are not interested what is l. So our state now is [left border][right border][direction][s]. State [v][l][r][s] becomes 2: [v][r][right][s] and [l][v][left][s]. We can exactly identify our current position. If we go left it's right border, and if we go right it's left border. Now, when we are in state [l][r][direction][s] and now we are in office v, we have to just find all offices q, l<=q<=r and c[v][q] != 0 and solve our problem for [l][q][right][s+1] and [q][r][left][s+1] and take minimum. For it we can use recursion. We can start from any office, so we have to solve problem for [0][v][left][0] and [v][n+1][right][0] and take minimum.
    We have n^22k states. In each state we check make not more than n operations. So algo works in O(n^3*k)

    trick

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    int dp[100][100][2][100];
    int vis[100][100][2][100];
    int c[100][100];
    int n,k,m,u,v,value;
    int work(int l,int r,int dir,int step)
    {
        if(step==(k-1)) return 0;
        if(vis[l][r][dir][step]) return dp[l][r][dir][step];
        vis[l][r][dir][step]=1;
        int bit=dir?r:l;int ret=1e9;
        for(int i=l+1;i<r;++i) if(c[bit][i])
        {
            ret=min(ret,c[bit][i]+work(i,r,0,step+1));
            ret=min(ret,c[bit][i]+work(l,i,1,step+1));
        }
        dp[l][r][dir][step]=ret;
        return ret;
    }
    
    
    int main()
    {
        scanf("%d %d",&n,&k);
        scanf("%d",&m);
        for(int i=1;i<=m;++i)
        {
            scanf("%d %d %d",&u,&v,&value);
            if(c[u][v]==0) c[u][v]=value;
            else c[u][v]=min(c[u][v],value);
        }
        int ans=1e9;
        for(int i=1;i<=n;++i)
        {
            ans=min(ans,work(0,i,1,0));
            ans=min(ans,work(i,n+1,0,0));
        }
        if(ans==1e9) puts("-1");else printf("%d
    ",ans);
    }
    
  • 相关阅读:
    【MSSQL】MSSQL还原单mdf文件报1813错误
    【JSP】JSP基础学习记录(二)—— JSP的7个动作指令
    【JSP】JSP基础学习记录(一)—— 基础介绍以及3个编译指令
    【Other】U盘FAT32转NTFS且无数据丢失
    python map()
    python关于分割与拼接的那些事
    python shutil.copy()用法
    python enumerate用法
    工作中遇到一些难题1_5
    廖雪峰读书笔记_文件读写总结_2016_12_23
  • 原文地址:https://www.cnblogs.com/chendl111/p/6767954.html
Copyright © 2011-2022 走看看