zoukankan      html  css  js  c++  java
  • 来更新一篇blog吧

    最近做了一下hackerrank的20/20的比赛。平时都只能过2题,这周顺利地通过了四道题目竟然。当妄图冲击衬衫的时候,发现剩下三个题一点招数都没有,之后就跑去看了一下node.js了。。。

    这次比赛的第四个题目是用cpp敲的,之前都是偷懒用python。

    题目链接

    Bike Racers

    【题意描述】

    在城市里有n个骑车的人,有m辆自行车,人可以同时沿着任意方向行走,每单位时间移动单位距离。要求出前k个到达自行车的人所花费的最小时间。人和自行车都用整数坐标表示。

    1 <= N <= 250
    1 <= M <= 250
    1 <= K <= min(N,M)
    0 <= xi,yi <= 107

    【思路】

    这一个题目,拿到之后没什么想法。然后感觉应该像是二分图的匹配问题。然后就去恶补了二分图,刷了三四道题目。第二天晚上回来,发现确实是二分图……那么大意就是求出这个图的一个子图,这个子图的二分图匹配数为k并且匹配的边中最大值最小。

    那么这道题可以用类似克鲁斯卡尔最小生成树的问题来解决。将边从小到大进行排序,依次添加到图中。每次添加检测匹配数,当匹配数为k的时候,最后添加的那条边就是所求解。匹配当然是采用匈牙利算法进行。

    算法确定,之后就是数据结构的问题:

    如何保存图是本题的关键。

    假设边以经按照权值排序完成。加边只修要O(1)的时间。

    题目的总体复杂度为V*匈牙利算法的复杂度(V为边数)

    匈牙利算法的复杂度为DFS的复杂度V*E(边数*点数)

    通常的题目中,使用邻接矩阵来保存图,匈牙利算法就退化成为了E*E*E(V=E*E),于是总体复杂度就变成了E^5。必须会TLE。

    世界就是如此美好,这个时候如果用边表来保存整个图,那么每次匈牙利算法的复杂度仍旧是V*E,总体复杂度就变为了(E*1+E*2+……+E*E*E)=1/2*(E^3)*(E+1)大约为E^4。看上去好很多了。

    排序的优化:

    为了让算法看上去更快一点,我又对排序这个地方产生了想法,如果排序的话,排序的复杂度为:

    V*logV = E*E*log(E*E) = 2E*ElogE。在最坏的情况下,加入了最后一条边才能出结果,这个时候复杂度是不会有改善的。这里考虑平均情况,也就是说不需要每次都用到所有的边,这个时候使用小顶堆可以胜任!

    以下是拙劣的代码。窃喜一下,还是觉得有长进的…

       1: #include <iostream>
       2: #include <cstring>
       3: #include <algorithm>
       4: #include <queue>
       5:  
       6: using namespace std;
       7:  
       8: struct Point {
       9:     long long x,y;
      10:     Point( long long _x, long long _y ) {
      11:         x = _x;
      12:         y = _y;
      13:     }
      14:     Point() {}
      15:     long long dis( Point p ) {
      16:         long long lx = x - p.x;
      17:         long long ly = y - p.y;
      18:         lx *= lx;
      19:         ly *= ly;
      20:         return lx+ly;
      21:     }
      22: };
      23:  
      24: struct Edge {
      25:     int y,next;
      26:     long long l;
      27:     Edge ( int _y, long long  _l, int _next ) {
      28:         y = _y;
      29:         next = _next;
      30:         l = _l;
      31:     }
      32:     Edge () {}
      33: };
      34:  
      35: struct E{
      36:     int x,y;
      37:     long long l;
      38:     E( int _x, int _y, long long _l ) {
      39:         x = _x;
      40:         y = _y;
      41:         l = _l;
      42:     }
      43:     E(){}
      44:     bool operator<( const E &e ) const {
      45:         return l > e.l;
      46:     }
      47: };
      48:  
      49: const int MAXSIZE = 255;
      50: const int NC = MAXSIZE*2;
      51:  
      52: priority_queue<E> Q;
      53:  
      54: int head[NC];
      55: Edge e[MAXSIZE*MAXSIZE];
      56: Point p[MAXSIZE];
      57: int visited[NC];
      58: int mark[NC];
      59:  
      60:  
      61: int e_len;
      62: int n,m,k;
      63: long long last;
      64:  
      65: void add( E ex ) {
      66:     e[e_len] = Edge(ex.y,ex.l,head[ex.x]);
      67:     head[ex.x] = e_len++;
      68: }
      69:  
      70: void input() {
      71:     while ( !Q.empty() ) {
      72:         Q.pop();
      73:     }
      74:     memset(e,-1,sizeof(e));
      75:     memset(head,-1,sizeof(head));
      76:     memset(p,0,sizeof(p));
      77:     e_len = 0;
      78:     cin>>n>>m>>k;
      79:     for ( int i = 0; i < n; i++ ) {
      80:         long long x,y;
      81:         cin>>x>>y;
      82:         p[i] = Point(x,y);
      83:     }
      84:     for ( int i = 0; i < m; i++ ) {
      85:         long long x,y;
      86:         cin>>x>>y;
      87:         Point t(x,y);
      88:         for ( int j = 0; j < n; j++ ) {
      89:             Q.push(E(j,MAXSIZE+i,t.dis(p[j])));
      90:         }
      91:     }
      92: }
      93:  
      94: int DFS( int x ) {
      95:     for ( int i = head[x]; i != -1; i = e[i].next ) {
      96:         int y = e[i].y;
      97:         if ( !visited[y] ) {
      98:             visited[y] = 1;
      99:             if ( ( -1 == mark[y] ) || ( DFS(mark[y]) ) ) {
     100:                 mark[y] = x;
     101:                 return 1;
     102:             }
     103:         }
     104:     }
     105:    return 0;
     106: }
     107:  
     108: bool test() {
     109:     memset(mark,-1,sizeof(mark));
     110:     int result = 0;
     111:     for ( int i = 0; i < n; i++ ) {
     112:         memset(visited,0,sizeof(visited));
     113:         result += DFS(i);
     114:     }
     115:     if ( result == k ) {
     116:         return true;
     117:     } else {
     118:         return false;
     119:     }
     120: }
     121:  
     122: void solve () {
     123:     for ( int i = 0; i < k; i++ ) {
     124:         E ex = Q.top();
     125:         Q.pop();
     126:         add(ex);
     127:         last = ex.l;
     128:     }
     129:     while ( !test() ) {
     130:         E ex = Q.top();
     131:         Q.pop();
     132:         add(ex);
     133:         last = ex.l;
     134:     }
     135:     cout<<last<<endl;
     136: }
     137:  
     138: int main() {
     139:     input();
     140:     solve();
     141: }
  • 相关阅读:
    中国石油昆仑加油卡
    157 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 02 异常内容简介
    156 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 01 Java常用工具类简介
    155 01 Android 零基础入门 02 Java面向对象 07 Java多态 07 多态知识总结 01 多态总结
    154 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 05 匿名内部类
    153 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 04 方法内部类
    152 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 03 静态内部类
    151 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 02 成员内部类
    150 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类概述 01 内部类概述
    149 01 Android 零基础入门 02 Java面向对象 07 Java多态 05 接口(重点)07 接口的继承
  • 原文地址:https://www.cnblogs.com/qoshi/p/3568436.html
Copyright © 2011-2022 走看看