1. 程式人生 > >最近對問題-蠻力法、分治法

最近對問題-蠻力法、分治法

蠻力法:

int ClosestPoints(point p[], int n){
    int index1, index2; //記錄下標
    int d, minDist = 1000; //設最大距離
    int i, j;
    for(i = 0; i < n - 1; i++ ){
        for(j = i+1; j < n; j++){
            d = (p[i].x - p[j].x)*(p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y);
            if( d < minDist){
                minDist = d;
                index1 = i;
                index2 = j;
            }
        }
    }
    printf("最近的點對是:第 %d 個點和第 %d 個點", index1 + 1, index2 + 1);

    return minDist;
}

分治法:

int ClosestPoints_1(point p[], int low, int high){
    int d1, d2, d3, d;
    point p1[N]; // 存放2d寬度內的點
    int mid, i, j, index;


    if(high - low == 1){ //兩個點時

        return Distance(p[low], p[high]);
    }
    if(high - low  == 2) //三個點時
    {

        d1 = Distance(p[low], p[low + 1]);
        d2 = Distance(p[low + 1], p[high]);
        d3 = Distance(p[low], p[high]);

        if((d1 > d2) && (d3 > d2))
            return d2;
        else if((d1 > d3) && (d2 > d3))
            return d3;
        else
            return d1;
    }
    mid = (low + high) / 2;

    d1 = ClosestPoints_1(p, low, mid);
    d2 = ClosestPoints_1(p, mid + 1, high);

    if(d1 <= d2)
        d = d1;
    else
        d = d2;

    index = 0;


    for(i = mid; (i >= low) && (p[mid].x - p[i].x < d); i--){
        p1[index++] = p[i];
    }

    for(i = mid + 1; (i <= high) && (p[i].x - p[mid].x < d); i++){
        p1[index++] = p[i];
    }

    QuickSort_y(p1, 0, index-1);


    for(i = 0; i <index; i++){
        for(j = i+1;j < index; j++){
            if(p1[j].y - p1[i].y >= d)
                break;
            else
            {

                d3 = Distance(p1[i], p1[j]);

                if(d3 < d){
                    d = d3;


                }
            }
        }
    }


    return d;

}

排序(快速排序):

int Partition_x(point p[], int first, int end){
    int i = first, j = end; //初始化待劃分區間
    while(i < j){
        while(i < j && p[i].x <= p[j].x) //右側掃描
            j--;
        if(i < j){     //將較小記錄交換到前面
            int temp = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp;

            int temp1 = p[i].y;  //換對應的y
            p[i].y = p[j].y;
            p[j].y = temp1;

            i++;
        }
        while( i < j && p[i].x <= p[j].x) //左側掃描
            i++;
        if(i < j)
        {                       //將較大的記錄交換到後面
            int temp = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp;

             int temp1 = p[i].y;  //換對應的y
            p[i].y = p[j].y;
            p[j].y = temp1;
            j--;
        }
    }
    return i;

}
void QuickSort_x(point p[], int first, int end){
    int pivot;
    if(first < end){
        pivot = Partition_x(p, first, end);
        QuickSort_x(p, first, pivot - 1);
        QuickSort_x(p, pivot+1, end);
    }

}

int Partition_y(point p[], int first, int end){
    int i = first, j = end;
    while(i < j){
        while(i < j && p[i].y <= p[j].y)
            j--;
        if(i < j){
            int temp = p[i].y;  //換y
            p[i].y = p[j].y;
            p[j].y = temp;

            int temp1 = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp1;
            i++;
        }
        while( i < j && p[i].y <= p[j].y)
            i++;
        if(i < j)
        {
            int temp = p[i].y; //換y
            p[i].y = p[j].y;
            p[j].y = temp;

            int temp1 = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp1;
            j--;
        }
    }
    return i;

}
void QuickSort_y(point p[], int first, int end){
    int pivot;
    if(first < end){
        pivot = Partition_y(p, first, end);
        QuickSort_y(p, first, pivot - 1);
        QuickSort_y(p, pivot+1, end);
    }

}

求距離:

int Distance(point a, point b){
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y)*(a.y - b.y);

}

列印:

void Print_Point(point p[]){
    int i ;
    for(i = 0; i < N; i++){
        printf("第%d個點  %d.%d    \n",i + 1, p[i].x, p[i].y);
    }
}

初始化:

void CreatPoint(point p[]){
    int i = 0;

   srand((unsigned)time(NULL)); //初始化隨機數
   /**
    srand()函式是隨機數發生器的初始化函式
    原型:void srand(unsigned seed);
    為了防止隨機數每次重複,常常使用系統時間來初始化
    即使用time函式來獲得系統時間,
    它的返回值為從 00:00:00 GMT, January 1, 1970 到現在所持續的秒數,
    然後將time_t型資料轉化為(unsigned)型再傳給srand函式,
    即: srand((unsigned) time(&t));
    還有一個經常用法,不需要定義time_t型t變數,
    即: srand((unsigned) time(NULL));
    直接傳入一個空指標
   **/

    for(i=0;i<N;i++)
    {
        p[i].x=rand()%1000; //獲取0到999 的隨機數
        p[i].y=rand()%1000;
    }



}
完整程式碼:
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
#include<time.h>
#define N 200


typedef struct point{
    int x;
    int y;

}point;

//最近對問題蠻力法
int ClosestPoints(point p[], int n){
    int index1, index2; //記錄下標
    int d, minDist = 1000; //設最大距離
    int i, j;
    for(i = 0; i < n - 1; i++ ){
        for(j = i+1; j < n; j++){
            d = (p[i].x - p[j].x)*(p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y);
            if( d < minDist){
                minDist = d;
                index1 = i;
                index2 = j;
            }
        }
    }
    printf("最近的點對是:第 %d 個點和第 %d 個點", index1 + 1, index2 + 1);

    return minDist;
}


//快速排序
int Partition_x(point p[], int first, int end){
    int i = first, j = end; //初始化待劃分區間
    while(i < j){
        while(i < j && p[i].x <= p[j].x) //右側掃描
            j--;
        if(i < j){     //將較小記錄交換到前面
            int temp = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp;

            int temp1 = p[i].y;  //換對應的y
            p[i].y = p[j].y;
            p[j].y = temp1;

            i++;
        }
        while( i < j && p[i].x <= p[j].x) //左側掃描
            i++;
        if(i < j)
        {                       //將較大的記錄交換到後面
            int temp = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp;

             int temp1 = p[i].y;  //換對應的y
            p[i].y = p[j].y;
            p[j].y = temp1;
            j--;
        }
    }
    return i;

}
void QuickSort_x(point p[], int first, int end){
    int pivot;
    if(first < end){
        pivot = Partition_x(p, first, end);
        QuickSort_x(p, first, pivot - 1);
        QuickSort_x(p, pivot+1, end);
    }

}

int Partition_y(point p[], int first, int end){
    int i = first, j = end;
    while(i < j){
        while(i < j && p[i].y <= p[j].y)
            j--;
        if(i < j){
            int temp = p[i].y;  //換y
            p[i].y = p[j].y;
            p[j].y = temp;

            int temp1 = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp1;
            i++;
        }
        while( i < j && p[i].y <= p[j].y)
            i++;
        if(i < j)
        {
            int temp = p[i].y; //換y
            p[i].y = p[j].y;
            p[j].y = temp;

            int temp1 = p[i].x;  //換x
            p[i].x = p[j].x;
            p[j].x = temp1;
            j--;
        }
    }
    return i;

}
void QuickSort_y(point p[], int first, int end){
    int pivot;
    if(first < end){
        pivot = Partition_y(p, first, end);
        QuickSort_y(p, first, pivot - 1);
        QuickSort_y(p, pivot+1, end);
    }

}
int Distance(point a, point b){
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y)*(a.y - b.y);

}
void Print_Point(point p[]){
    int i ;
    for(i = 0; i < N; i++){
        printf("第%d個點  %d.%d    \n",i + 1, p[i].x, p[i].y);
    }
}
//分治法
int ClosestPoints_1(point p[], int low, int high){
    int d1, d2, d3, d;
    point p1[N]; // 存放2d寬度內的點
    int mid, i, j, index;


    if(high - low == 1){ //兩個點時

        return Distance(p[low], p[high]);
    }
    if(high - low  == 2) //三個點時
    {

        d1 = Distance(p[low], p[low + 1]);
        d2 = Distance(p[low + 1], p[high]);
        d3 = Distance(p[low], p[high]);

        if((d1 > d2) && (d3 > d2))
            return d2;
        else if((d1 > d3) && (d2 > d3))
            return d3;
        else
            return d1;
    }
    mid = (low + high) / 2;

    d1 = ClosestPoints_1(p, low, mid);
    d2 = ClosestPoints_1(p, mid + 1, high);

    if(d1 <= d2)
        d = d1;
    else
        d = d2;

    index = 0;


    for(i = mid; (i >= low) && (p[mid].x - p[i].x < d); i--){
        p1[index++] = p[i];
    }

    for(i = mid + 1; (i <= high) && (p[i].x - p[mid].x < d); i++){
        p1[index++] = p[i];
    }

    QuickSort_y(p1, 0, index-1);


    for(i = 0; i <index; i++){
        for(j = i+1;j < index; j++){
            if(p1[j].y - p1[i].y >= d)
                break;
            else
            {

                d3 = Distance(p1[i], p1[j]);

                if(d3 < d){
                    d = d3;


                }
            }
        }
    }


    return d;

}
void CreatPoint(point p[]){
    int i = 0;

   srand((unsigned)time(NULL)); //初始化隨機數
   /**
    srand()函式是隨機數發生器的初始化函式
    原型:void srand(unsigned seed);
    為了防止隨機數每次重複,常常使用系統時間來初始化
    即使用time函式來獲得系統時間,
    它的返回值為從 00:00:00 GMT, January 1, 1970 到現在所持續的秒數,
    然後將time_t型資料轉化為(unsigned)型再傳給srand函式,
    即: srand((unsigned) time(&t));
    還有一個經常用法,不需要定義time_t型t變數,
    即: srand((unsigned) time(NULL));
    直接傳入一個空指標
   **/

    for(i=0;i<N;i++)
    {
        p[i].x=rand()%1000; //獲取0到999 的隨機數
        p[i].y=rand()%1000;
    }



}

int main()
{
    point p[N];

    CreatPoint(p);

    Print_Point(p);
    printf("\n\n");
    int d = ClosestPoints(p, N);
    printf("最近距離為:%d", d);

    QuickSort_x(p, 0, N-1);

    d = ClosestPoints_1(p, 0, N-1);
    printf("\n\n最近距離為:%d", d);

    return 0;
}

執行結果:



相關推薦

最近問題-治法

蠻力法:int ClosestPoints(point p[], int n){ int index1, index2; //記錄下標 int d, minDist = 1000; //設最大距離 int i, j; for(i = 0; i

演算法設計與分析--求最大子段和問題(治法動態規劃法) C++實現

演算法設計與分析--求最大子段和問題 問題描述: 給定由n個整陣列成的序列(a1,a2, …,an),求該序列形如 的子段和的最大值,當所有整數均為負整數時,其最大子段和為0。 利用蠻力法求解: int maxSum(int a[],int n) { int ma

最大子段和問題-治法動態規劃法

蠻力法:int maxSum1(int a[], int n){ int i; int j; int maxSum = 0; for(i = 0; i < n; i++){ int sum = 0; fo

治法最近問題——Java 實現

public class ClosestPair2{ public static void main(String[] args) {  /**   *輸入需要比較的點的對數存在變數n中   */  Scanner in=new Scanner(System.in);  System.out.println(

排序問題(治法

蠻力法: 選擇排序法: 演算法思想:在剩餘序列中選出最小(或最大)的關鍵字,和剩餘序列的第一個關鍵字交換位置,依次選擇下去(每次掃描結束找出最小的一個元素依次放在前面的位置),直至使整個序列有序。 程式碼實習: #include<iostream> using names

最近問題之無內部排序治法有內部排序治法

#include <iostream> #include <vector> #include <algorithm> #include <string> #include <stdlib.h> #include <math.h>

六中常用演算法設計:窮舉治法動態規劃貪心回溯和分支限界

演算法設計之六種常用演算法設計方法 1.直接遍歷態(窮舉法)        程式執行狀態是可以遍歷的,遍歷演算法執行每一個狀態,最終會找到一個最優的可行解;適用於解決極小規模或者複雜度線性增長,而線

使用治法求解最近

問題描述 對於平面上給定的N個點,給出所有點對的最短距離,即輸入是平面上的N個點,輸出是N點中具有最短距離的兩點。 求解 建立點類,使之具有兩個屬性,x座標和y座標 class myPoint { public: int x; //x座標 i

演算法設計--&&治法最近問題(C++實現)

最近對問題? 設p1=(x1,y1), p2(x2,y2), ....,pn=(xn,yn)是平面上n個點構成的集合S,最近對問題就是找出集合S中距離最近的點對。 兩種演算法思想: 1. 蠻力法:顧名思義,利用正常的思維,使用強硬的方式求解出結果。 2. 分治法:分治,分而

解決最近問題

跑個O(n^2),沒啥可說的,直接上程式碼和資料。 C++程式碼 #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; const int maxn = 10005; typedef st

最近問題(

問題描述:最近對問題是求解平面點集n個點中距離最近的兩個點間的問題。為簡單起見,在二維座標平面來考慮該問題。如果討論的點以標準二維座標形式給出,則有點Pi(Xi,Yi)和Pj(Xj,Yj),二者的兩點間距離可以利用公式d(Pi,Pj)=√(Xj-Xi)*(Xj-Xi)+(Yj

最近問題(C實現)

#include <stdio.h> #include <math.h> /* 我們可以避免求平方根,竅門是忽略平方根函式,而只比較(x[i]-x[j])^2+(y[i]

利用解決最近問題

#include<iostream>#include<stack>#include<vector>using namespace std;stack<int> KnapSack(int c,vector<int> w

c++最近問題

#include <iostream> #include <math.h> #include <stdlib.h> using namespace std; #define M 10000 struct P { int x;

在求解“最近”問題中的應用(JAVA)

最近對問題是在計算幾何問題中最簡單的,是指在一個包含n個點的集合中,找到距離最近的兩個點,我們這裡只研究二維空間中的版本,高維計算基本類似,區別只在於計算兩點之間距離的公式略有不同,下面是標準的歐幾里

一組資料先進行快排,再找出眾數

 環境 :Windows10, VS2010 #include <iostream> #include <string> using namespace std; int Partition (int r[],int first,int end)

3.1.1之選擇排序

特性 序表 sel div wap 數組 排列 code for 選擇排序開始的時候,我們掃描整個列表,找到它的最小元素,然後和第一個元素交換,將最小元素放到它在有序表中的最終位置上。然後我們從第二個元素開始掃描列表,找到最後n-1個元素中的最小元素,再和第

——冒泡排序

情況 情況下 復雜度 pre n-1 std nbsp 思想 交換 冒泡排序是蠻力法的另一個經典體現。 算法思想:比較列表中相鄰的元素,如果是逆序的話,就交換他們的位置。重復多次之後,最大的元素就排到了最後一個位置。第二遍操作將第二個元素排到了倒數第二個位置上,這樣一直依次

C語言實現快速排序治法

下一個 enter hang partition 等於 就是 tor log markdown title: 快速排序法(quick sort) tags: 分治法(divide and conquer method) grammar_cjkRuby: true ---

找犯人——(算

body 至少 clu a+b pos nbsp div sin main 某地刑偵大隊對涉及六個嫌疑人的一樁疑案進行分析: (1)A、B至少有一人作案;(2)A、E、F三人中至少有兩人參與作案;(3)A、D不可能是同案犯;(4)B、C或同時作案,或與本案無關;(5)C、D