暴力法解决最近对问题和凸包问题-实现可视化

目录

最近对问题

凸包问题


最近对问题

顾名思义就是采用蛮力法求出所有点之间的距离,然后进行比较找出第一个最近对,一个一个进行比较。

大概思路就是如图(每个圈代表一个数对)

第一个和其他四个比较

第二个和其他三个比较

.......

最后比较最小的

image-20240510191434898

代码

图形化界面主要是easyx的graphics

#include<iostream>
#include <fstream>
#include<graphics.h>
#include <conio.h>
using namespace std;
#define Max 20  //20个点的凸包问题
#define maxn 10000
#define time 15
​
typedef struct {
    int a;
    int b;
}point;
void draw_point(point x[]);
void draw_line(int a, int b, int c, int d);
void judge(point x[]);
​
int main() {
    point x[Max];
​
    ifstream in("a.txt");
    cout << "从txt中读取点坐标如下:" << endl;
    for (int i = 0; i < 20; i++)
    {
        in >> x[i].a;
        in >> x[i].b;
    }
    for (int i = 0; i < 20; i++)
    {
        cout << i + 1 << ":" << "(" << x[i].a << "," << x[i].b << ")" << endl;
    }
    cout << endl << endl;
    in.close();
    cout << "存储的数据如下:" << endl;
    draw_point(x);
    judge(x);
    getchar();
    return 0;
}
​
void judge(point x[]) {
    int i, j, a, b, c, n, num1 = 0, num2 = 0;
    int flag;
    for (i = 0; i < Max; i++)
    {
        for (j = i + 1; j < Max; j++)
        {
            b = x[i].a - x[j].a;
            a = x[j].b - x[i].b;
            c = x[i].a * x[j].b - x[j].a * x[i].b;
​
            for (n = 0; n < Max; n++)
            {
                if (n != i && n != j)
                {
                    flag = x[n].a * a + x[n].b * b;
                    if (flag < c)
                        num1++;
                    else if (flag > c)
                        num2++;
                    else {
                        num1++;
                        num2++;
                    }
                    ;
                }
            }
            if (num1 == 18 || num2 == 18)
            {
                cout << "如下两点是极边:" << "(" << x[i].a << "," << x[i].b << ")" << "(" << x[j].a << "," << x[j].b << ")" << endl;
                draw_line(x[i].a, x[i].b, x[j].a, x[j].b);
            }
            num1 = num2 = 0;
        }
    }
​
}
void draw_point(point x[]) {
    initgraph(880, 680, SHOWCONSOLE);
    setorigin(320, 240);
    int a, b;
    for (int i = 0; i < Max; i++) {
        a = x[i].a * time;
        b = x[i].b * time;
        fillcircle(a, b, 4);
    }
}
void draw_line(int a, int b, int c, int d)
{
    line(a * time, b * time, c * time, d * time);
}

运行结果

先写一个a.txt文件的点(20个)

img

运行(可视化界面)

img

凸包问题

凸包问题就是在一个有n个点集的平面上,找出所有的“极点”,这些极点所构成的边界能够把其他所有的点都能包含在内。

思路

由两个点连起来的直线会将平面分成两部分,其中半个平面的点都满足ax+by>c ,另一半平面中的点都满足ax+by<c ,对于线上的点来说满足ax+by=c。因此,算法的思路就是对于每个点带入ax+by-c,判断表达式结果的符号是否相同即可。

代码

#include<iostream>
#include<fstream>
#include<graphics.h>
#include<cmath>
#include<algorithm>
using namespace std;
​
#define Max 20 // 最大点数
#define maxn 10000
#define time 15
​
typedef struct {
    int a;
    int b;
} point;
​
void draw_point(point x[]);
void draw_line(int a, int b, int c, int d);
void closest_pair(point x[]);
​
int main() {
    point x[Max];
​
ifstream in("points.txt"); 
cout << "从txt文件中读取点坐标:" << endl;
    for (int i = 0; i < Max; i++) {
        in >> x[i].a;
        in >> x[i].b;
    }
    for (int i = 0; i < Max; i++) {
        cout << i + 1 << ": (" << x[i].a << ", " << x[i].b << ")" << endl;
    }
    cout << endl << endl;
    in.close();
​
    cout << "存储的数据如下:" << endl;
    draw_point(x);
    closest_pair(x);
    getchar();
    closegraph(); // 关闭图形窗口
    return 0;
}
​
void closest_pair(point x[]) {
    int min_distance = INT_MAX;
    int pair1 = -1, pair2 = -1;
​
    for (int i = 0; i < Max; i++) {
        for (int j = i + 1; j < Max; j++) {
            int distance = pow(x[i].a - x[j].a, 2) + pow(x[i].b - x[j].b, 2);
            if (distance < min_distance) {
                min_distance = distance;
                pair1 = i;
                pair2 = j;
            }
        }
    }
​
    cout << "最近的点对:" << endl;
    cout << "(" << x[pair1].a << ", " << x[pair1].b << ") 和 (" << x[pair2].a << ", " << x[pair2].b << ")" << endl;
​
    // 绘制最近的点对连线
    draw_line(x[pair1].a, x[pair1].b, x[pair2].a, x[pair2].b);
}
​
void draw_point(point x[]) {
    initgraph(880, 680, SHOWCONSOLE);
    setorigin(320, 240);
    int a, b;
    for (int i = 0; i < Max; i++) {
        a = x[i].a * time;
        b = x[i].b * time;
        fillcircle(a, b, 4);
    }
}
​
void draw_line(int a, int b, int c, int d) {
    line(a * time, b * time, c * time, d * time);
}

运行结果

先写一个points.txt文件的点(20个)

img

运行:(可视化界面)

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用C语言解决凸包问题实现可视化动态效果,可以使用以下步骤: 1. 首先,需要使用凸包算法来计算给定点集的凸包。常见的凸包算法有Graham扫描算法和Jarvis步进算法。 2. 在计算凸包时,需要使用一个数据结构来存储点的坐标信息。可以使用C语言中的结构体来表示点,如下所示: ``` typedef struct { double x; double y; } Point; ``` 3. 在计算凸包时,需要将点按照一定的顺序进行排序。可以使用C语言中的qsort函数来实现,如下所示: ``` int cmp(const void* a, const void* b) { Point* p1 = (Point*)a; Point* p2 = (Point*)b; if (p1->x < p2->x) { return -1; } else if (p1->x > p2->x) { return 1; } else { return 0; } } qsort(points, n, sizeof(Point), cmp); ``` 4. 在计算凸包时,需要将点按照一定的顺序进行连接。可以使用C语言中的图形库来实现可视化效果,如下所示: ``` void drawLine(Point p1, Point p2) { line(p1.x, p1.y, p2.x, p2.y); delay(100); } for (int i = 0; i < hullSize - 1; i++) { drawLine(hull[i], hull[i+1]); } drawLine(hull[hullSize-1], hull[0]); ``` 这里使用了一个自定义的drawLine函数来绘制线段,并使用了delay函数来实现动态效果。 完整的C语言实现代码如下所示: ``` #include <stdio.h> #include <stdlib.h> #include <graphics.h> #include <math.h> #define MAX_POINTS 1000 typedef struct { double x; double y; } Point; int cmp(const void* a, const void* b) { Point* p1 = (Point*)a; Point* p2 = (Point*)b; if (p1->x < p2->x) { return -1; } else if (p1->x > p2->x) { return 1; } else { return 0; } } double crossProduct(Point p1, Point p2, Point p3) { double x1 = p2.x - p1.x; double y1 = p2.y - p1.y; double x2 = p3.x - p2.x; double y2 = p3.y - p2.y; return x1 * y2 - x2 * y1; } void drawLine(Point p1, Point p2) { line(p1.x, p1.y, p2.x, p2.y); delay(100); } int main() { int gd = DETECT, gm; initgraph(&gd, &gm, ""); Point points[MAX_POINTS]; int n = 0; while (!kbhit() && n < MAX_POINTS) { if (ismouseclick(WM_LBUTTONDOWN)) { clearmouseclick(WM_LBUTTONDOWN); int x = mousex(); int y = mousey(); points[n].x = x; points[n].y = y; n++; putpixel(x, y, WHITE); } } qsort(points, n, sizeof(Point), cmp); Point hull[MAX_POINTS]; int hullSize = 0; for (int i = 0; i < n; i++) { while (hullSize >= 2 && crossProduct(hull[hullSize-2], hull[hullSize-1], points[i]) <= 0) { hullSize--; } hull[hullSize] = points[i]; hullSize++; } int hullStart = 0; for (int i = n - 2; i >= 0; i--) { while (hullSize >= hullStart + 2 && crossProduct(hull[hullSize-2], hull[hullSize-1], points[i]) <= 0) { hullSize--; } hull[hullSize] = points[i]; hullSize++; } for (int i = 0; i < hullSize - 1; i++) { drawLine(hull[i], hull[i+1]); } drawLine(hull[hullSize-1], hull[0]); getch(); closegraph(); return 0; } ``` 在运行程序时,可以使用鼠标点击来添加点,程序会自动计算凸包并进行可视化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值