《关于为了一杯果茶所以7点半起床给舍友写java作业这档事》
import java.util.Scanner;
class MyPoint {
private double x, y;
public MyPoint(){
x = y = 0;
}
public MyPoint(double x, double y){
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public double distance(MyPoint myPoint){
return distance(myPoint.x, myPoint.y);
}
public double distance(double x, double y){
return Math.sqrt((this.x - x) * (this.x - x) + (this.y - y) * (this.y - y));
}
}
public class Shit {
public static void main(String[] args) {
int n, k;
Scanner input = new Scanner(System.in);
n = input.nextInt();
k = input.nextInt();
MyPoint[] point = new MyPoint[n];//存点
for(int i = 0; i < n; ++i){
point[i] = new MyPoint(Math.random() * 100, Math.random() * 100);//生成随机点
}
MyPoint[] centre = new MyPoint[k];//中心点
boolean[] vis = new boolean[n];//标记数组,用于防止初始质心选重
for(int i = 0; i < k; ++i){
int id = (int)(Math.random() * n);//随机选取k个质心
while(vis[id]){//直到找到新的没有被使用过的点,才作为质心
id = (int)(Math.random() * n);
}
vis[id] = true;//更新标记
centre[i] = new MyPoint(point[id].getX(), point[id].getY());
}
int[] id = new int[n];//记录n个点属于哪个簇
while(true){
int[] num = new int[k];//记录簇中的点的数量
boolean p = true;//用于判断什么时候结束循环,当每个点的id都不变的时候就结束
for(int i = 0; i < n; ++i){
int idd = 0;//记录属于哪个簇
double minx = point[i].distance(centre[0]);//最小距离
for(int j = 1; j < k; ++j){//计算该点到所有点的距离,找到最小距离对应的下标idd
if(minx > point[i].distance(centre[j])){
idd = j;
minx = point[i].distance(centre[j]);
}
}
if(id[i] != idd){//如果不属于上次的簇,则说明和上次的分类不同,则不能退出循环,更新标记p
id[i] = idd;//更新id
p = false;
}
++num[idd];//更新簇的点的数量
}
if(p)break;//如果所有的簇不变,则退出循环
for(int i = 0; i < k; ++i){//初始化中心点的值
centre[i].setX(0);
centre[i].setY(0);
}
for(int i = 0; i < n; ++i){//求和,便于求质心
centre[id[i]].setX(centre[id[i]].getX() + point[i].getX());
centre[id[i]].setY(centre[id[i]].getY() + point[i].getY());
}
for(int i = 0; i < k; ++i){//计算每个簇的点的质心
centre[i].setX(centre[i].getX() / num[i]);
centre[i].setY(centre[i].getY() / num[i]);
}
}
for(int i = 0; i < k; ++i){
System.out.printf("第%d个簇的质心: (%f, %f)\n", i+1, centre[i].getX(), centre[i].getY());
for(int j = 0; j < n; ++j){
if(id[j] == i)System.out.printf("(%f, %f) ", point[j].getX(), point[j].getY());
}
System.out.println();
}
}
}