CodeVs 1615 数据备份

题目:数据备份

链接:Here

题意:有n个点在一条线上,每次连线可以连接两个点(每个点只能被连一次),要求找出m个连线,他们的和最小(连线权值就是两点距离),输出最小的和。给出n、m和每个点的坐标。

思路:

  可反悔贪心。

  容易得出连线必然是选择相邻的点组成,那么从连线权值最小的开始选(用优先队列实现),假设现在有6个连线(1、2、3、4、5、6),如果第一次选了3,但后面有可能发现w[3] + w[x](后面找到的一个满足条件的权值最小的连线)> w[2] + w[4](正常情况下选了3,就不可以选择2、4了),那么我可以反悔,重新选择2、4而抛弃3,要想做到这样,在把w[3]算入总和时,得把w[2]+w[4]-w[3]放入优先队列,以供日后反悔,基于假设,w[2]+w[4]-w[3]<w[x],那么先出来的就是w[2]+w[4]-w[3],此时sum+w[2]+w[4]-w[3]和最初选了2、4的结果一致,当然,在把w[2]+w[4]-w[3]算入总和时,得把这一块的左边连线w[1]与右边连线w[5]再结合,也就是w[1]+w[5]-(w[2]+w[4]-w[3]),放入优先队列,以供后面可以反悔。容易得到这个贪心是正确的。

AC代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #include<math.h>
 5 #include<set>
 6 #include<map>
 7 #include<list>
 8 #include<stack>
 9 #include<queue>
10 #include<vector>
11 #include<string>
12 #include<iostream>
13 #include<algorithm>
14 using namespace std;
15 #define lson rt<<1
16 #define rson rt<<1|1
17 #define N 100010
18 #define M 100010
19 #define Mod 1000000007
20 #define LL long long
21 #define INF 1000000007
22 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
23 #define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
24 #define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
25 #define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
26 #define MT(x,i) memset(x,i,sizeof(x))
27 #define gcd(x,y) __gcd(x,y)
28 const double PI = acos(-1);
29 
30 struct Node
31 {
32   int w,l,r,pos;
33   bool friend operator < (Node a,Node b)
34   {
35     return a.w>b.w;
36   }
37 }w[N];
38 
39 bool vis[N];
40 priority_queue<Node> q;
41 
42 int main()
43 {
44   int n,k;
45   scanf("%d%d",&n,&k);{
46     int pre = 0;
47     FOR(i,1,n){
48       scanf("%d",&w[i].w);
49       int tmp = w[i].w;
50       w[i].w -= pre;
51       pre = tmp;
52 
53       w[i].pos = i;
54       w[i].l = i-1;
55       w[i].r = i+1;
56     }
57     w[2].l = w[n].r = 0;
58 
59     //while(q.size()) q.pop();
60     FOR(i,2,n){
61       q.push(w[i]);
62     }
63     int sum = 0;
64     FOR(i,1,k){
65       Node tmp;
66       while(q.size()){
67         tmp = q.top();
68         q.pop();
69         if(tmp.w == w[tmp.pos].w) break;
70       }
71       //printf("%d %d %d %d\n",tmp.l,tmp.r,tmp.pos,tmp.w);
72       tmp = w[tmp.pos];
73       sum += tmp.w;
74       Node now;
75       now.pos = tmp.pos;
76       now.l = w[tmp.l].l;
77       now.r = w[tmp.r].r;
78       w[now.l].r=now.pos;
79       w[now.r].l=now.pos;
80 
81       if(tmp.l==0 || tmp.r==0) now.w=INF;
82       else now.w = w[tmp.l].w + w[tmp.r].w - tmp.w;
83       w[now.pos]=now;
84 
85       //printf("===%d %d %d %d\n",now.l,now.r,now.pos,now.w);
86       w[tmp.l].w = INF;
87       w[tmp.r].w = INF;
88       q.push(now);
89     }
90     printf("%d\n",sum);
91   }
92   return 0;
93 }
posted @ 2016-09-29 23:34  hchlqlz  阅读(250)  评论(0编辑  收藏  举报