• Codeforces #366 (Div. 2) D. Ant Man (贪心)


    https://blog.csdn.net/liangzhaoyang1/article/details/52215276  原博客

    原来好像是个dp题,不过我看了别人的博客使用贪心做的 复杂度(n^2)

    题意:在一个数轴上有n个点,每个点有5个值x,a,b,c,d,你每次可以从一个点i跳跃到另外一个点j。

    如果j在i的右边,则需要花费abs(x[i]-x[j])+c[i]+b[j]。

    如果j在i的左边,则需要花费abs(x[i]-x[j])+d[i]+a[j],

    一开始你位于s点,你的目的是遍历所有的点1遍并且最后停在e点,求最小花费.(注意:每个点最多只能遍历1遍)

    题解:

    初始化链:next[s] = e表示直接从起点s跳到终点e。

    然后枚举其他所有的点,将它们一个一个插入到链中(寻找加入到链中的什么地方花费最低)

    例如样例:
    ①:初始化:4->3
    ②:插入编号为1的点,显然1只能插入一个地方,插入后:4->1->3
    ③:插入编号为2的点,2可以插入两个地方(4和1中间或1和3中间),可以轻松算出插入4和1中间成本更低,所以
    插入后:4->2->1->3
    ④:编号为3和4的点是起点和终点,跳过
    ⑤:插入编号为5的点,5可以插入三个地方,其中插入1和3中间成本更低,插入后:4->2->1->5->3
    ⑥:插入编号为6的点,……,插入后:4->2->1->6->5->3。

    代码中的实现: 

    用 dis函数处理距离。

    对 i=1~n按顺序 插,碰到s和e就跳过。 对每一个i,都找到一个最恰当的插的位置k,处理 k和前后的关系。

    花费 用t表示,在计算t的时候 要减去原来dis(u,next[u]),这样后面直接就可以 ans+=minn。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include <cctype>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<string>
     8 #include<cmath>
     9 #include<set>
    10 #include<vector>
    11 #include<stack>
    12 #include<queue>
    13 #include<map>
    14 using namespace std;
    15 #define ll long long
    16 #define mem(a,x) memset(a,x,sizeof(a))
    17 #define se second    
    18 #define fi first
    19 const int INF= 0x3f3f3f3f;
    20 const int N=3e5+5;
    21 
    22 int n,s,e;
    23 ll x[5005],a[5005],b[5005],c[5005],d[5005];
    24 ll net[5005]; 
    25 
    26 ll dis(int l,int r)
    27 {
    28     if(l<r) return abs(x[l]-x[r])+d[l]+a[r];
    29     if(l>r) return abs(x[l]-x[r])+c[l]+b[r];
    30 }
    31 
    32 int main()
    33 {
    34     cin>>n>>s>>e;
    35     for(int i=1;i<=n;i++)  scanf("%lld",&x[i]);
    36     for(int i=1;i<=n;i++)  scanf("%lld",&a[i]);
    37     for(int i=1;i<=n;i++)  scanf("%lld",&b[i]);
    38     for(int i=1;i<=n;i++)  scanf("%lld",&c[i]);
    39     for(int i=1;i<=n;i++)  scanf("%lld",&d[i]);
    40     
    41     net[s]=e;
    42     ll ans=dis(s,e);
    43     for(int i=1;i<=n;i++)
    44     {
    45         if(i==s||i==e) continue;
    46         
    47         int u=s;
    48         ll minn=1e18;
    49         int k;
    50         while(u!=e)
    51         {
    52             ll t=dis(u,i)+ dis(i,net[u])- dis(u,net[u]);
    53             if(t<minn)
    54             {
    55                 minn=t;
    56                 k=u;
    57             }
    58             u=net[u];
    59         }
    60         ans+=minn;
    61         //接下来把i插入这个线性结构中 
    62         net[i]=net[k]; //把i插在k的后面,k的next 就变成了 i的next 
    63         net[k]=i;  //k的next变成 i  
    64     } 
    65     cout<<ans;
    66 }
  • 相关阅读:
    利用GitHub和Hexo打造免费的个人博客 coder
    Android基础——项目的文件结构(二) coder
    25个Android酷炫开源UI框架 coder
    MarkDown使用教程(In Atom) coder
    Android基础——项目的文件结构(一) coder
    25类Android常用开源框架 coder
    Android Activity启动黑/白屏原因与解决方式 coder
    我的window phone 开发第一步
    Entity Framework 4 In Action 读书笔记
    最近在制作一套ASP.NET控件,已初见雏形
  • 原文地址:https://www.cnblogs.com/thunder-110/p/9488426.html
Copyright © 2020-2023  润新知