最近對問題-蠻力法、分治法
蠻力法:
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