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 }

猜你喜欢

转载自www.cnblogs.com/thunder-110/p/9488426.html