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 }