<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    so true

    心懷未來,開創未來!
    隨筆 - 160, 文章 - 0, 評論 - 40, 引用 - 0
    數據加載中……

    算法:距離之和最小

    題目:NxM矩陣中散落K點,求一個點,該點到各個的距離之和最短,兩點之間距離的定義:折線距離(即只能橫著走或豎著走)。
    解法:求K個點的重心,從矩陣左上角,先橫后豎遍歷,找到第K/2個點所在的行;先豎后橫找到第K/2個點所在的列;用這個行和這個列定位的點即為所求。
    原理:假定P點為所求,距離和為S,P點到任何一點的距離都由水平距離+垂直距離構成;若水平移動,豎直方向的距離之和保持不變;同理垂直方向。因此,該問題可以歸約為一個一維問題:數軸上散落N個點,求一個點到各個點的距離之和最小,下面進行簡單論證:
    a b c d e f g七個點,d點即位所求;如果是f點,那么該問題可以歸約為b c d e f五個點的問題(在比較d和f誰更優時,a和g同時存在或不存在對問題的影響是一致的),此時,顯然f不如d。
    推廣:K個點,每個點都有一個系數q,兩點之間距離定義為:折線距離 x 系數k;解法依舊:先計算K個點的總系數Q,遍歷方法依舊,只不過這次是找到一個點,截至這個點累加起來的系數之和剛好達到Q/2。
    領悟:實則就是求重心。
    代碼:和窮舉法做了對比,結果一致。
    #include <iostream>
    #include <stdlib.h>
    #include <string>
    #include <vector>
    #include <map>
    #include <math.h>
    #include <set>
    using namespace std;
    class MatchPointFinder {
    public:
        double GetDistanceBetweenTwoPoints(int x1, int y1, int x2, int y2, double alpha) const {
            return (abs(x1 - x2) + abs(y1 - y2)) * alpha;
            //return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
            //two methods will *not* be equivalent under the following way of calculating distance, for the case in "main"
            //return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
        }
        double CalcSumDistance(int x, int y) {
            double dist = 0.0f;
            for (typeof(m_node_pos.begin()) it = m_node_pos.begin(), it4End = m_node_pos.end(); it4End != it; ++it) {
                dist += GetDistanceBetweenTwoPoints(it->first.first, it->first.second, x, y, it->second);
            }
            return dist;
        }
        MatchPointFinder(): m_width(0), m_height(0), m_match_point_x(0), m_match_point_y(0), m_total_weight(0), m_nodes(NULL) {
        }
        void ValidateEquivalenceOfTwoMethods(int trial_num = 1000) {
            for (int i = 0; i < trial_num; ++i) {
                int width = 5 + rand() % 100;
                int height = 5 + rand() % 100;
                Reset();
                RandomInit(width, height);
                if (!CompareTwoMethod()) {
                    Try();
                    break;
                } else {
                    printf("two methods are equivalent under %d x %d array scale\n", height, width);
                }
            }
        }
        void Try() {
            FindMatchPointByEnumerating(m_match_point_x, m_match_point_y);
            printf("total weight is %f\n", m_total_weight);
            PrintMap(false);
            PrintMap();
            int old_mp_x = m_match_point_x;
            int old_mp_y = m_match_point_y;
            FindMatchPointByMedianMethod(m_match_point_x, m_match_point_y);
            PrintMap(false);
            if (old_mp_x == m_match_point_x && old_mp_y == m_match_point_y) {
                printf("two methods are equivalent under %d x %d array scale\n", m_height, m_width);
            } else {
                printf("two methods are *not* equivalent under %d x %d array scale\n", m_height, m_width);
            }
        }
        template <typename T>
        T abs(const T& t) const {
            return t > 0 ? t : -1 * t;
        }
        bool CompareTwoMethod() {
            FindMatchPointByEnumerating(m_match_point_x, m_match_point_y);
            int old_mp_x = m_match_point_x;
            int old_mp_y = m_match_point_y;
            FindMatchPointByMedianMethod(m_match_point_x, m_match_point_y);
            if (old_mp_x == m_match_point_x && old_mp_y == m_match_point_y) {
                return true;
            } else if (abs(m_node_dist[std::make_pair(old_mp_x, old_mp_y)] - m_node_dist[std::make_pair(m_match_point_x, m_match_point_y)]) < 0.000001) {
                return true;
            }
            return false;
        }
        ~MatchPointFinder() {
            Reset();
        }
        void RandomInit(int width = -1, int height = -1, bool init_random = true) {
            if (-1 != width) {
                m_width = width;
            }
            if (-1 != height) {
                m_height = height;
            }
            srand(time(NULL));
            m_nodes = new double*[m_height];
            memset(m_nodes, 0, sizeof(double*) * m_height);
            for (int i = 0; i < m_height; ++i) {
                if (!init_random) {
                    m_nodes[i] = new double[m_width];
                    memset(m_nodes[i], 0, sizeof(int) * m_width);
                } else {
                    for (int j = 0; j < m_width; ++j) {
                        if (0 == j) {
                            m_nodes[i] = new double[m_width];
                            memset(m_nodes[i], 0, sizeof(int) * m_width);
                        }
                        m_nodes[i][j] = ((rand() % 10) >= 5 ? (double)(1 + rand() % 3) / 5 : 0);
                        if (m_nodes[i][j]) {
                            m_node_pos[std::make_pair(i, j)] = m_nodes[i][j];
                            m_total_weight += m_nodes[i][j];
                        }
                    }
                }
            }
        }
        void AddNode(int x, int y) {
            m_nodes[x][y] = 1;
            m_node_pos[std::make_pair(x, y)] = 1;
            m_total_weight += 1;
        }
        void FindMatchPointByMedianMethod(int& mp_x, int& mp_y) {
            double collected_weight = 0;
            mp_x = -1;
            for (int i = 0; i < m_height; ++i) {
                for (int j = 0; j < m_width; ++j) {
                    if (m_nodes[i][j] <= 0) {
                        continue;
                    }
                    collected_weight += m_nodes[i][j];
                    if (collected_weight >= m_total_weight / 2) {
                        mp_x = i;
                        break;
                    }
                }
                if (-1 != mp_x) {
                    break;
                }
            }
            collected_weight = 0;
            mp_y = -1;
            for (int j = 0; j < m_width; ++j) {
                for (int i = 0; i < m_height; ++i) {
                    if (m_nodes[i][j] <= 0) {
                        continue;
                    }
                    collected_weight += m_nodes[i][j];
                    if (collected_weight >= m_total_weight / 2) {
                        mp_y = j;
                        break;
                    }
                }
                if (-1 != mp_y) {
                    break;
                }
            }
        }
        void FindMatchPointByEnumerating(int& mp_x, int& mp_y) {
            double shortest_sum_dist = std::numeric_limits<double>::max();
            for (int i = 0; i < m_height; ++i) {
                for (int j = 0; j < m_width; ++j) {
                    double dist = CalcSumDistance(i, j);
                    m_node_dist[std::make_pair(i, j)] = dist;
                    if (dist < shortest_sum_dist) {
                        shortest_sum_dist = dist;
                        mp_x = i;
                        mp_y = j;
                    }
                }
            }
        }
        void PrintMap(bool print_dist = true) {
            printf("%4s ", " ");
            for (int i = 0; i < m_width; ++i) {
                printf("      (%2d) ", i);
            }
            printf("\n");
            for (int i = 0; i < m_height; ++i) {
                printf("(%2d) ", i);
                for (int j = 0; j < m_width; ++j) {
                    if (i == m_match_point_x && j == m_match_point_y) {
                        if (print_dist) {
                            printf("*%.1f[%2.1f] ", m_nodes[i][j], m_node_dist[std::make_pair(i, j)]);
                        } else {
                            printf("      *%.1f ", m_nodes[i][j]);
                        }
                    } else {
                        if (print_dist) {
                            printf("%.1f[%2.1f] ", m_nodes[i][j], m_node_dist[std::make_pair(i, j)]);
                        } else {
                            printf("      %.1f ", m_nodes[i][j]);
                        }
                    }
                }
                printf("\n");
            }
            printf("\n");
        }
        void Reset() {
            if (m_nodes) {
                for (int i = 0; i < m_height; ++i) {
                    delete [] m_nodes[i];
                }
                delete [] m_nodes;
            }
            m_nodes = NULL;
            m_width = 0;
            m_height = 0;
            m_match_point_x = 0;
            m_match_point_y = 0;
            m_total_weight = 0;
            m_node_pos.clear();
            m_node_dist.clear();
        }
    private:
        int m_width;
        int m_height;
        int m_match_point_x;
        int m_match_point_y;
        double m_total_weight;
        double** m_nodes;
        std::map<std::pair<int, int>, double> m_node_pos;
        std::map<std::pair<int, int>, double> m_node_dist;
    };
    int main(int argc, char* argv[]) {
        int width = 5;
        int height = 5;
        if (argc > 1) {
            height = atoi(argv[1]);
        }
        if (argc > 2) {
            width = atoi(argv[2]);
        }
        MatchPointFinder mpf;
        //mpf.RandomInit(width, height);
        //mpf.Try();
        //return 0;
        mpf.ValidateEquivalenceOfTwoMethods(1000);
        return 0;
        /*
                               ( 0)       ( 1)       ( 2)       ( 3)       ( 4)
                    ( 0)          1          1          0          0          1
                    ( 1)          1          0          0          1          0
                    ( 2)          1          1          0          1          0
                    ( 3)          0          0       *  1          1          0
                    ( 4)          1          1          1          1          1
        */
        mpf.Reset();
        mpf.RandomInit(5, 5, false);
        mpf.AddNode(0, 0);
        mpf.AddNode(0, 1);
        mpf.AddNode(0, 4);
        mpf.AddNode(1, 0);
        mpf.AddNode(1, 3);
        mpf.AddNode(2, 0);
        mpf.AddNode(2, 1);
        mpf.AddNode(2, 3);
        mpf.AddNode(3, 2);
        mpf.AddNode(3, 3);
        mpf.AddNode(4, 0);
        mpf.AddNode(4, 1);
        mpf.AddNode(4, 2);
        mpf.AddNode(4, 3);
        mpf.AddNode(4, 4);
        mpf.Try();
        return 0;
    }

    posted on 2015-02-07 20:34 so true 閱讀(1041) 評論(0)  編輯  收藏 所屬分類: C&C++

    主站蜘蛛池模板: 99久久99热精品免费观看国产| 亚洲激情视频图片| 亚洲精品视频免费观看| 免费一级成人毛片| 一二三四在线观看免费中文在线观看| 国产18禁黄网站免费观看| 免费看黄网站在线看| 亚洲人成人无码网www国产| xvideos永久免费入口| 亚洲午夜无码久久久久| 蜜桃视频在线观看免费视频网站WWW| 久久亚洲国产精品| 精品免费久久久久久久| 亚洲欧洲专线一区| 少妇亚洲免费精品| 国产一区二区三区免费观看在线| 亚洲av不卡一区二区三区| 国产h视频在线观看网站免费| 国产精品亚洲四区在线观看| 在线观看永久免费视频网站| 一级做a爱过程免费视频高清| 国产亚洲人成网站观看| 色播精品免费小视频| 亚洲av无码一区二区三区人妖 | 免费在线观看的网站| 日本亚洲欧美色视频在线播放| 亚洲精品综合久久| 久久w5ww成w人免费| 亚洲暴爽av人人爽日日碰| 亚洲精品尤物yw在线影院| 最近免费中文在线视频| 国产成人亚洲精品91专区高清 | 国产综合免费精品久久久| 色拍自拍亚洲综合图区| 国产高清在线精品免费软件| baoyu122.永久免费视频| 亚洲色欲色欱wwW在线| 国产亚洲AV手机在线观看| 4hu四虎最新免费地址| 国产高潮久久免费观看| 亚洲 欧洲 视频 伦小说|